fprime-ground-input-tracing
GitHub用于追踪F Prime代码中数值来源,判断其是否源自地面输入(如指令、参数或上行链路),以辅助安全代理识别由地面控制的可达路径和断言溢出风险。
触发场景
安装
npx skills add nasa/fprime --skill fprime-ground-input-tracing -g -y
SKILL.md
Frontmatter
{
"name": "fprime-ground-input-tracing",
"description": "Use when tracing a value in F Prime code back to determine whether it originates from ground input (commands, parameters, uplink, telemetry filters, file uplink, or any uplink-stack component)."
}
Skill: Trace a value back to determine if it is ground-controlled
The security agent flags asserts, overflow paths, and validation gaps reachable by ground input (commands, parameters, uplink, telemetry filters, file uplink). To do so, it must trace each predicate in an assert or arithmetic operation back to its source class:
programmer-constant— compile-time constant, no input reachability.internal-state— derived from internal component state, not ground-reachable (modulo prior ground influence on that state, see §4).ground-input— derived from a ground command argument, parameter, uplink data, or any other value the ground operator controls.hardware-input— derived from a driver input or hardware register. Tracing for this class lives infprime-hardware-input-tracing.
This skill is the trace procedure for the ground-input class.
1. Ground-input entry points
The following F Prime constructs receive ground input directly:
| Entry point | Where the data enters |
|---|---|
| Command arguments | Component::CMD_<NAME>_cmdHandler(...) parameters declared in the .fpp command definition. |
| Parameters | Component::paramSet_<NAME>(...) and Component::paramGet_<NAME>(...) flows; values originate from the parameter database, written from ground. |
| Uplinked file content | Svc::FileUplink-derived input ports / handler bodies. |
| Telemetry filter / packet selection | Svc::TlmPacketizer, Svc::ComLogger configurations that ground can influence. |
| Cmd opcodes / sequencing | Svc::CmdDispatcher dispatch path; opcode is ground-controlled, dispatch args inherit. |
| Async input ports labeled "from ground" in the topology | Any async input port wired in the topology from a ground-facing component (CmdDispatcher, ComQueue, FileUplink, etc.). |
| Deframer / framing layer | Svc::Deframer and any *Deframer-suffix component; the deframed buffer originates from the uplink byte stream and is ground-controlled. |
| Router | Svc::Router, Svc::FprimeRouter, and other router components that route uplink frames to handlers; routed payload inherits ground-input class. |
| Accumulator components | Uplink accumulators that gather partial frames before forwarding; their accumulated buffer is ground-input. |
| Detector components | Svc::CmdSequencer and similar detectors that scan an uplink buffer for sentinels / patterns; detected payload is ground-input. |
| ByteStream drivers (conditionally) | Drv::ByteStreamDriverModel-derived components carry ground-origin OR hardware-origin data depending on the topology wiring. The agent MUST consult the topology before deciding which tracing skill applies; see §4. |
Each handler parameter at one of these entry points is ground- input at the moment it enters the agent's component. The trace proceeds forward from there.
2. Forward trace within a component
For an offending line L in component C (e.g., FW_ASSERT(x < LIMIT)):
- Identify the variable
xbeing asserted on. - Walk backward from
LwithinC's method body using simple intra-procedural data-flow:- Direct assignment:
x = y;→ tracey. - Function-call result:
x = foo(a, b);→ iffoois inC, recurse; iffoois inFw/Os/Drv, consult the source- class rules in §3. - Arithmetic combination:
x = a + b;→ trace bothaandb;xisground-inputif either is. - Member access:
x = this->m_foo;→ markm_fooasinternal-statefor this trace; cross-reference any code path that writesthis->m_foofrom a ground-input source class (§4).
- Direct assignment:
- If the variable is a handler argument at an entry point in §1,
classify as
ground-inputand stop. - If the variable is a literal or a
constexprvalue, classify asprogrammer-constantand stop.
3. Library and primitive source classes
| Construct | Source class |
|---|---|
Literal, constexpr, enum value, static const |
programmer-constant |
Fw::Time::getTimeBase(), Os::IntervalTimer, similar |
internal-state |
Os::File::read() results (when reading a path that ground supplied) |
ground-input (file content is ground-uplinked) |
| Component port input parameters at the entry points in §1 | ground-input |
| Random / unpredictable internal state | internal-state |
Fw::Buffer payload received over an external port |
depends on the port's wiring; consult the topology |
When in doubt, the agent classifies as the more dangerous class
(ground-input if there is any plausible ground-reachable path)
and appends a maintainer ping per maintainer-lookup.
4. Cross-procedural and cross-component flow
When the data crosses component boundaries (via an output port to another component's input port), the trace must follow the wiring in the topology:
- From the offending line, identify the variable's origin within the local component.
- If the origin is an input port handler argument, look up the
port in the topology files (
topology.fpp/instances.fpp/*Topology.cpp) to find the source component and port. - Recurse on the source component's output port: what value does it pass? Apply §2 within that component.
- Continue until reaching a §1 entry point (→
ground-input), a §3 primitive (→ classify), or a hardware-input port (→ hand off tofprime-hardware-input-tracing).
The topology files relevant to the trace live in:
Ref/Top/topology.fpp— the F Prime reference deployment's topology declaration.Ref/Top/RefTopology.cpp— the reference topology's generated C++ wiring.Ref/Top/instances.fpp— instance declarations for the reference deployment.Svc/Subtopologies/*/topology.fppandSvc/Subtopologies/*/instances.fpp— subtopologies that are composed into deployment topologies.Svc/<Component>/<Component>.fpp(for component-internal port declarations).
Other deployments (mission-specific) use the same file naming inside
their own <Deployment>/Top/ directory.
ByteStream driver disambiguation. When the trace reaches a port
wired to a Drv::ByteStreamDriverModel-derived component, the agent
must read the topology to determine whether that driver is the
uplink-side (ground) or a hardware-side (radio, serial, network)
byte stream. Same code, different upstream — the trace continues in
this skill or hands off to fprime-hardware-input-tracing
accordingly. If the topology is ambiguous (e.g., the same
ByteStream driver is shared between ground and hardware paths), the
agent classifies as ground-input (the more dangerous class) and
adds a maintainer ping.
5. Worked example — ground-reachable assert
// In Svc/CmdDispatcher/CmdDispatcher.cpp (illustrative)
void CmdDispatcher::Dispatch_cmdHandler(
FwOpcodeType opCode,
U32 cmdSeq,
U32 dispatchOpCode // ← command argument
) {
FW_ASSERT(dispatchOpCode < this->m_dispatchMax); // L
// ...
}
Trace from line L:
- Variable
dispatchOpCode. - Backward in the function body: no reassignment; the parameter is the source.
- The parameter is a command-handler argument → §1 →
ground-input.
The predicate operand dispatchOpCode is ground-input. Therefore
FW_ASSERT on it is a ground-reachable assert →
security-review.agent.md category 1 → **must fix**.
Suggestion: replace the assert with a validation:
if (dispatchOpCode >= this->m_dispatchMax) {
this->log_WARNING_HI_InvalidOpcode(dispatchOpCode);
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
return;
}
6. Worked example — value derived from internal state but
ground-influenced
this->m_dispatchMax = newMax; // newMax came from CMD_SET_MAX
// ...
FW_ASSERT(dispatchOpCode < this->m_dispatchMax);
Tracing m_dispatchMax:
m_dispatchMaxisinternal-state.- Cross-reference: is there a write path to
m_dispatchMaxfrom a ground-input source class? CMD_SET_MAX_cmdHandler(newMax)writes it →newMaxisground-input.- Therefore
m_dispatchMaxis effectivelyground-input(with sticky propagation: once an internal-state variable is written from a ground source, treat it asground-inputfor the duration of subsequent traces).
The assert is still a ground-reachable assert via a one-step indirection.
**must fix**.
7. Confidence calibration
The agent reports high confidence when:
- The trace reaches a §1 entry point within at most 3 hops, OR
- The trace is constrained to one component and reaches a §3 primitive cleanly.
The agent reports low confidence when:
- The trace crosses ≥ 4 component boundaries.
- The trace involves dynamic dispatch (function pointers, virtual calls into a base class with multiple subclasses).
- The agent cannot resolve a topology wiring (the relevant
topology.fpp/instances.fpp/*Topology.cppis not in the agent's read scope, or the wiring is conditional on a build option).
Low confidence → tag at the right severity + maintainer ping per
maintainer-lookup.
8. One-line summary
Walk backwards from the offending variable; classify origin as programmer-constant / internal-state / ground-input / hardware-input. Cross-component flow follows topology wiring. When in doubt, the more dangerous class wins and the maintainer is pinged.
版本历史
- 7d8f579 当前 2026-08-20 11:33


