T09 · Insecure Skill Coding Practices
- Location
AGENTS.md:39- Finding
Unbounded SPI polling can indefinitely halt firmware execution
- Content
View full analysis
Vulnerability Details
File Location:
AGENTS.md:39-43
Vulnerability Type: Unbounded busy-wait and misleading non-blocking implementation
Risk Level: MediumVulnerable Code
c void spi_write_byte(SPI_TypeDef *spi, uint8_t data) { while (!LL_SPI_IsActiveFlag_TXE(spi)); LL_SPI_TransmitData8(spi, data); while (LL_SPI_IsActiveFlag_BSY(spi)); }Technical Analysis
The function polls the SPI
TXEandBSYflags without a timeout, cancellation mechanism, watchdog interaction, or error return. Although the surrounding heading describes the transfer as non-blocking, bothwhilestatements are synchronous and can wait forever.The SPI flags may remain in an unexpected state because of peripheral misconfiguration, clock failure, hardware faults, bus contention, or deliberate manipulation of an attached device. If that occurs, control never returns to the caller. This contradicts the skill's explicit requirement in
AGENTS.md:8andSKILL.md:24that peripheral drivers must never block indefinitely.Because this is presented as an authoritative implementation template, generated firmware may reproduce the unsafe pattern.
Attack Path
- Firmware generated from the skill incorporates the provided SPI transfer pattern.
- An attacker with access to the device or SPI bus induces a peripheral fault, clock disruption, or bus condition that prevents
TXEfrom becoming active orBSYfrom clearing. - The processor remains inside one of the unbounded polling loops.
- The affected task or entire bare-metal execution path stops making progress.
- The device becomes unavailable until a watchdog or external reset occurs. Repeatedly inducing the condition may create a persistent denial of service.
Impact Assessment
This issue does not grant additional software privileges or direct access to confidential information. Its primary impact is availability loss within firmware that ...[truncated 320 chars]
- Remediation
View remediation
Remediation Suggestions
- Replace unbounded flag polling with deadline-based waits.
- Return a status value such as
bool, an STM32 error code, or a project-specific result enum. - Reset or safely reinitialize the SPI peripheral after a timeout where supported.
- Propagate transfer failures to the caller and place outputs in a defined safe state.
- Use interrupt- or DMA-driven transfers if the example is intended to be genuinely non-blocking.
- Add tests that hold
TXEinactive andBSYactive to verify bounded recovery.
Example hardened interface:
c spi_status_t spi_write_byte(SPI_TypeDef *spi, uint8_t data, uint32_t deadline_ticks) { while (!LL_SPI_IsActiveFlag_TXE(spi)) { if (deadline_expired(deadline_ticks)) { return SPI_STATUS_TIMEOUT; } } LL_SPI_TransmitData8(spi, data); while (LL_SPI_IsActiveFlag_BSY(spi)) { if (deadline_expired(deadline_ticks)) { return SPI_STATUS_TIMEOUT; } } return SPI_STATUS_OK; }
