Back to skill

Security audit

horus

Security checks for vulnerabilities and agentic risk

Overview

This is a documentation-only protocol/reference implementation package with real implementation-quality cautions but no hidden execution, persistence, credential use, or exfiltration behavior in the artifact.

Installing this skill is reasonable if you treat it as experimental documentation. Do not copy the reference Python into production without replacing assert-based validation, recording predicate evaluation failures, adding privacy controls for exports, and reconciling the checksum/determinism claims with the actual export behavior.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
skills.md:237
Finding
Security-Relevant Input Validation Uses Removable Python Assertions<![CDATA[ ## Vulnerability Details **File Location**: `skills.md:237-239, 338-340, 389-405`; duplicated in `CS-RV_Protocol_Whitepaper.md:553-554, 607-609, 636-651` **Vulnerability Type**: Validation bypass through Python assertions **Risk Level**: Medium ### Vulnerable Code ```python # skills.md:237-239 assert len(coordinates) > 0, "Coordinates cannot be empty" assert 0 <= confidence <= 1, f"Confidence must be in [0,1], got {confidence}" assert observer_id, "Observer ID required" ``` Additional security-relevant checks use the same unsafe pattern: ```python # skills.md:338-340 assert state_hash in self.state_ledger, f"State {state_hash} not found" assert constraint_id in self.constraint_registry, f"Constraint {constraint_id} not found" assert 0 <= severity <= 1, f"Severity must be in [0,1], got {severity}" ``` ```python # skills.md:389-405 assert state_hash in self.state_ledger, f"State {state_hash} not found" state = self.state_ledger[state_hash] coords = state.coordinates assert all(0 <= d < len(coords) for d in target_dims), \ f"Invalid target dimensions {target_dims} for {len(coords)}D state" if projection_type == "orthogonal": projected = [coords[i] for i in target_dims] else: raise ValueError(f"Unknown projection type: {projection_type}") assert self._estimate_entropy(projected) <= self._estimate_entropy(coords), \ "Entropy increased during projection!" ``` ### Technical Analysis Python assertions are debugging constructs, not reliable runtime validation. Running the interpreter with optimization enabled, such as `python -O`, removes all `assert` statements. Consequently, the documented implementation may accept empty coordinate arrays, invalid confidence or severity values, and empty observer identifiers. Checks that references exist and projection dimensions are valid are also removed. This conflicts with the document's characterization of the implementation as production-ready. The same design is duplicated in the whitepap ...[truncated 1255 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace every security-relevant assertion with unconditional validation: ```python if not coordinates: raise ValueError("Coordinates cannot be empty") if not 0 <= confidence <= 1: raise ValueError(f"Confidence must be in [0,1], got {confidence}") if not observer_id: raise ValueError("Observer ID required") ``` 2. Validate references before accessing dictionaries: ```python if state_hash not in self.state_ledger: raise KeyError(f"State {state_hash} not found") ``` 3. Validate that projection dimensions are integers, non-negative, in range, and subject to an appropriate maximum count. 4. Retain assertions only for internal conditions that cannot be influenced by untrusted data. 5. Add automated tests that run under both standard Python and `python -O`. 6. Apply the same corrections to both `skills.md` and `CS-RV_Protocol_Whitepaper.md` so implementers do not copy an unsafe variant. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
skills.md:482
Finding
Constraint Predicate Exceptions Cause Silent Fail-Open Validation<![CDATA[ ## Vulnerability Details **File Location**: `skills.md:482-491`; duplicated in `CS-RV_Protocol_Whitepaper.md:674-681` **Vulnerability Type**: Fail-open exception handling and incomplete audit logging **Risk Level**: Medium ### Vulnerable Code ```python # skills.md:482-491 for cid, constraint in self.constraint_registry.items(): if constraint.is_forbidden: try: if not constraint.predicate(obs): self.record_violation( hash_id, cid, severity=0.5, metadata={'auto_detected': True} ) except Exception: # Predicate evaluation failure is not system failure pass ``` The whitepaper contains an even broader handler: ```python # CS-RV_Protocol_Whitepaper.md:674-681 for cid, constraint in self.constraint_registry.items(): if constraint.is_forbidden: try: if not constraint.predicate(obs): self.record_violation(hash_id, cid, severity=0.5) except: pass # Predicate evaluation failure is not system failure ``` ### Technical Analysis The implementation suppresses every exception raised during constraint evaluation. In the whitepaper, the bare `except` also catches exceptions such as `KeyboardInterrupt` and `SystemExit`. A constraint predicate that fails for a prohibited state produces neither a violation record nor an error record. The state has already been added to the ledger before `_check_violations()` is called, so it remains accepted despite incomplete validation. This behavior is fail-open. It also contradicts the stated audit-transparency objective because the exported trace provides no indication that a constraint could not be evaluated. Because predicates are caller-supplied callables, errors can arise accidentally from malformed data or intentionally from a predicate designed to raise only for states that should be rejected. ...[truncated 1272 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Never silently discard predicate failures. Record a distinct validation-error event containing the constraint ID, state hash, timestamp, and a sanitized error classification. 2. Catch only anticipated exception types. Do not use a bare `except`. 3. Select and document a failure policy. For forbidden constraints, fail closed or mark the state as unvalidated pending review: ```python try: satisfied = constraint.predicate(obs) except (TypeError, ValueError, KeyError) as exc: self.record_validation_error( state_hash=hash_id, constraint_id=cid, error_type=type(exc).__name__, ) satisfied = False ``` 4. Execute untrusted predicates in an isolated worker with time, memory, and CPU limits if external users can provide callable logic. 5. Prevent predicates from mutating ledger state and validate their return value is strictly Boolean. 6. Add tests for predicates that raise exceptions, time out, return non-Boolean values, or receive malformed observations. 7. Apply equivalent fixes to the implementations in both Markdown files. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (10)

Intent-Code Divergence

High
Confidence
98% confidence
Finding
The specification promises integrity protection and complete export, but the implementation only serializes JSON bytes and omits both a checksum and the actual executable predicates for constraints. Consumers may falsely trust exported traces as complete and tamper-evident, enabling audit bypass, integrity confusion, and unsafe reliance on incomplete forensic data in distributed or multi-node settings.

Intent-Code Divergence

Medium
Confidence
85% confidence
Finding
The canonical data structures define `ORTHOGONAL`, `STEREOGRAPHIC`, and `PROBABILISTIC` projection types, but the implementation accepts only `orthogonal` and raises an error otherwise. Because the file presents this as a reference implementation for the spec and later defines completeness as implementing all operations, the documentation overstates implementation parity with the formal protocol.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The specification states as a postcondition for REGISTER_STATE that there is 'No global state mutation', but the reference implementation stores the observation in `self.state_ledger` and then calls `_check_violations`, which can append to `self.violation_log`. This is an active contradiction between the documented operation semantics and the implemented behavior, not merely omitted detail.

Intent-Code Divergence

Medium
Confidence
91% confidence
Finding
The document says declared constraints are added to a registry and 'do NOT enforce globally' with 'No enforcement cascade', implying constraints are passive data until explicitly validated. In the implementation, `register_state` immediately invokes `_check_violations`, which iterates all registered constraints and evaluates them against each new observation, creating violation records automatically.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
EXPORT_TRACE is defined to serialize the complete system state, including observations, constraints, violations, observer IDs, and metadata, but the operation description does not prominently warn that invoking it may expose sensitive data. In the context of a distributed AI coordination protocol, this increases the risk of accidental data exfiltration, privacy leakage, and overbroad sharing of audit artifacts across nodes or operators.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding
Suspicious Unicode normalization or mixed-script content

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The `export_trace` docstring states the output is deterministic, but the implementation injects `datetime.utcnow().isoformat()` into the serialized data. That means two calls over identical internal state will produce different bytes, directly contradicting the documented intent.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The export_trace routine serializes the complete ledger, constraints, violations, observer identifiers, timestamps, and arbitrary metadata, but the documentation does not warn that this may contain sensitive or identifying data. In a real deployment, users may export and share audit traces assuming they are harmless, leading to confidentiality leakage of operational telemetry or embedded secrets in metadata.

Intent-Code Divergence

Low
Confidence
91% confidence
Finding
The `register_state` docstring lists a postcondition of `No global state mutation`, yet the method writes to `self.state_ledger` and increments `self.stats['total_observations']`. For this object, those are state mutations, so the documentation contradicts the actual behavior.

Missing User Warnings

Low
Confidence
82% confidence
Finding
The documented automated tool invocation specifies both an input directory and an output directory for generated code, implying file-system writes as part of the migration process. The markdown presents this as a ready-to-run command without a caution about reviewing the destination path or the effects on existing files.

Static analysis

No suspicious patterns detected.