Back to skill

Security audit

Lineage Claws

Security checks for vulnerabilities and agentic risk

Overview

This skill is a local provenance verifier, but it overstates its cryptographic guarantees and produces proof-like outputs that are not actually signed or independently verified.

Install only if you need a project-specific MOSES lineage helper and are comfortable with it writing local OpenClaw governance/audit files. Do not treat its badge or attestation output as independent cryptographic proof, a digital signature, legal custody evidence, or a complete ledger integrity check without additional external validation.

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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/lineage.py:167
Finding
Live Ledger Verification Validates Only the Public Anchor Field<![CDATA[ ## Vulnerability Details **File Location**: `scripts/lineage.py:167-178` and `scripts/lineage.py:224-234` **Vulnerability Type**: Incomplete cryptographic chain validation **Risk Level**: High ### Vulnerable Code ```python # scripts/lineage.py:167-178 if os.path.exists(LEDGER_PATH): with open(LEDGER_PATH) as f: lines = [l.strip() for l in f if l.strip()] if lines: first = json.loads(lines[0]) if first.get("previous_hash") != MOSES_ANCHOR: print("[LINEAGE FAIL] Ledger genesis does not trace to origin anchor.") print(" Chain custody broken — this is not a sovereign implementation.") sys.exit(1) print(f"[LINEAGE OK] Layer 0: anchor traces to origin-cycle filing.") ``` The machine-readable check uses the same incomplete validation: ```python # scripts/lineage.py:224-234 if os.path.exists(LEDGER_PATH): with open(LEDGER_PATH) as f: lines = [l.strip() for l in f if l.strip()] if lines: first = json.loads(lines[0]) if first.get("previous_hash") != MOSES_ANCHOR: sys.exit(1) print("LINEAGE:OK") sys.exit(0) ``` ### Technical Analysis Both verification paths inspect only the first ledger entry's `previous_hash`. Because `MOSES_ANCHOR` is publicly computable from constants embedded in the source, possession of this value provides no authentication. The implementation does not: - Recompute the first entry's hash from its canonical contents. - Compare the recomputed genesis hash with `record["genesis_hash"]`. - Validate that the first entry is a legitimate genesis event. - Recompute hashes for subsequent ledger entries. - Verify that each subsequent `previous_hash` equals the preceding entry's hash. - Reject an absent or empty ledger. - Detect modification, deletion, reordering, or insertion of later entries. Consequently, this is an anchor-field equality check rather than full ledger-chain verification. It contradicts the documented claim that ...[truncated 1146 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Define and enforce a strict schema for genesis and ordinary ledger entries. - Require a nonempty ledger when live-ledger verification is claimed. - Remove each entry's stored `hash`, canonicalize all remaining fields, and recompute SHA-256. - Compare every recomputed hash with the stored hash. - Require the genesis entry's `previous_hash` to equal `MOSES_ANCHOR`. - Require the recomputed genesis hash to equal `record["genesis_hash"]`. - For every later entry, require `entry["previous_hash"]` to equal the verified hash of the preceding entry. - Reject malformed JSON, duplicate sequence numbers, missing fields, reordered entries, and trailing invalid data. - Make `cmd_check` call the same full verification routine as `cmd_verify` so the two commands cannot diverge. - If authenticity against local file replacement is required, authenticate a trusted chain head using a protected signing key or an external transparency log. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/archival.py:175
Finding
Archival Verification Does Not Recompute Hashes from Stored Block Contents<![CDATA[ ## Vulnerability Details **File Location**: `scripts/archival.py:175-182` and `scripts/archival.py:245-254` **Vulnerability Type**: Incomplete stored-data integrity verification **Risk Level**: Medium ### Vulnerable Code ```python # scripts/archival.py:175-182 for i, (s, e) in enumerate(zip(stored_chain, expected)): if s.get("hash") != e["hash"]: print(f"[ARCHIVAL FAIL] Block {i} hash mismatch — chain integrity broken at seq {i}.") sys.exit(1) if s.get("previous_hash") != e["previous_hash"]: print(f"[ARCHIVAL FAIL] Block {i} previous_hash mismatch — linkage broken at seq {i}.") sys.exit(1) ``` The machine-readable check validates only the top-level head: ```python # scripts/archival.py:245-254 try: stored = load_chain() if not stored: sys.exit(1) expected = build_chain() if stored.get("head") != archival_head(expected): sys.exit(1) print("ARCHIVAL:OK") sys.exit(0) except Exception: sys.exit(1) ``` ### Technical Analysis `cmd_verify` compares the stored `hash` and `previous_hash` strings with values generated from the hard-coded expected chain. It never computes `block_hash()` over the actual stored block contents. As a result, fields such as `claim`, `claim_type`, `external_ref`, `author`, and `seq` can be changed while retaining the original `hash` and `previous_hash` strings. The verifier will accept those altered contents. The `cmd_check` implementation is weaker still: it checks only whether the stored top-level `head` equals a public deterministic value and does not inspect the stored blocks at all. A cryptographic digest protects data only when the verifier recomputes the digest from the data being verified. Comparing copied digest strings without binding them to stored content does not establish integrity. ### Attack Path 1. Run `archival.py build` or obtain a valid `archival_chain.json`. 2. Modify one or more stored provenance fields, such as the auth ...[truncated 919 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - For every stored block, copy the block and remove its `hash` field. - Recompute `block_hash()` from the complete canonical stored block and compare it with the stored hash. - Validate the genesis predecessor and each subsequent block's linkage using the previously verified hash. - Validate sequence numbers, required fields, data types, block count, and ordering. - If the claims are intended to be fixed, compare each complete canonical stored block with the corresponding expected block after cryptographic verification. - Recompute the top-level head from the verified stored chain rather than merely comparing it with a hard-coded expected head. - Refactor `cmd_check` to invoke the same comprehensive verification routine as `cmd_verify`. - Use atomic, permission-restricted writes for the state file to reduce accidental corruption and local replacement risk. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/lineage.py:290
Finding
Purported Signed Attestations Use a Forgeable Unkeyed Hash<![CDATA[ ## Vulnerability Details **File Location**: `scripts/lineage.py:290-322` **Vulnerability Type**: Missing cryptographic authentication **Risk Level**: High ### Vulnerable Code ```python attest = { "attested_at": datetime.now(timezone.utc).isoformat(), "system": "MO§ES™ Constitutional Governance", "custody": "Ello Cello LLC / Deric McHenry", "patent_serial": "63/877,177", "doi": "https://zenodo.org/records/18792459", "lineage_anchor": MOSES_ANCHOR, "genesis_hash": record["genesis_hash"], "archival_head": arch_head, "anchored_at": record["anchored_at"], "lineage_status": "SOVEREIGN", "verification": "python3 lineage.py verify", } attest["attestation_hash"] = hashlib.sha256( json.dumps(attest, sort_keys=True, separators=(",", ":")).encode() ).hexdigest() print(json.dumps(attest, indent=2)) ``` ### Technical Analysis The command is documented as producing a “signed attestation,” but `attestation_hash` is an ordinary unkeyed SHA-256 content digest. It uses no private signing key, HMAC secret, certificate, hardware-backed identity, or trusted external timestamp. Because all inputs and the hashing algorithm are public, any party can create arbitrary attestation fields and calculate a matching digest. The digest can detect accidental changes only when compared against a separately trusted copy; it cannot prove the identity of the issuer or distinguish an authentic statement from a forgery. The command also accepts the stored `genesis_hash` without proving that it corresponds to a valid genesis record or fully verified ledger. ### Attack Path 1. Create a JSON object using the same public field structure. 2. Set `custody`, `lineage_status`, `genesis_hash`, timestamps, and other assertions to arbitrary attacker-selected values. 3. Serialize the object using sorted keys and compact separators. 4. Calculate SHA-256 over that public serialization. 5. Add the result as `attestation_hash`. 6. Present the object ...[truncated 645 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Rename `attestation_hash` to `content_hash` and remove all “signed” claims until actual authentication is implemented. - Use a standard signature algorithm such as Ed25519 rather than a custom cryptographic construction. - Protect the private key with restrictive permissions, an operating-system key store, hardware security module, or external signing service. - Publish the corresponding public key through a trusted, independently verifiable channel. - Add signer identity, signature algorithm, key identifier, schema version, issuance time, and expiration time to the signed payload. - Define one canonical serialization format and sign the exact canonical bytes. - Verify the full lineage and ledger before issuing an attestation. - Provide a verification command that validates the signature against a pinned trusted public key and rejects unknown, revoked, or expired keys. - If replay is relevant, include a verifier-provided nonce or audience identifier in the signed statement. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/lineage.py:21
Finding
Archival Provenance Chain Is Not Cryptographically Bound to the Lineage Anchor<![CDATA[ ## Vulnerability Details **File Location**: `scripts/lineage.py:21-30` and `scripts/archival.py:105-126` **Vulnerability Type**: Missing cryptographic binding between custody layers **Risk Level**: Medium ### Vulnerable Code The lineage anchor is derived without the archival head: ```python # scripts/lineage.py:21-30 _ORIGIN_COMPONENTS = ( "MO§ES™", "Serial:63/877,177", "DOI:https://zenodo.org/records/18792459", "SCS Engine", "Ello Cello LLC", ) MOSES_ANCHOR = hashlib.sha256( "|".join(_ORIGIN_COMPONENTS).encode("utf-8") ).hexdigest() ``` The archival chain independently starts from zero and produces a head that is never incorporated into `MOSES_ANCHOR`: ```python # scripts/archival.py:105-126 def build_chain() -> list[dict]: """Construct the archival chain from PROVENANCE_CLAIMS.""" chain = [] prev = "0" * 64 # Genesis has no predecessor for claim in PROVENANCE_CLAIMS: block = { "seq": claim["seq"], "claim": claim["claim"], "claim_type": claim["claim_type"], "external_ref": claim["external_ref"], "author": claim["author"], "previous_hash": prev, } h = block_hash(block) block["hash"] = h chain.append(block) prev = h return chain ``` ### Technical Analysis The documented model claims a three-layer chain: ```text archival chain -> archival head -> anchor -> live ledger ``` The implementation instead constructs two independent deterministic values: - An archival head derived from hard-coded provenance claims. - A lineage anchor derived from a separate tuple of hard-coded strings. The archival head is not an input to the anchor hash, and no authenticated transition record links the head to the anchor. `cmd_verify` merely checks the two structures independently before printing that three-layer custody is confirmed. Independent validity does not prove that one object is downstream of ...[truncated 1527 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Define a single normative anchor derivation specification and make the documentation and executable implementation identical. - Cryptographically bind Layer -1 to Layer 0 by including the verified archival head in the anchor derivation, for example through a versioned and domain-separated structure. - Alternatively, create a signed transition record containing the archival head, lineage anchor, schema version, timestamp, and signer identity. - Verify the archival chain completely before accepting its head as an anchor input. - Store and verify the explicit transition record during every lineage verification. - Add fixed test vectors containing the exact canonical bytes, expected archival head, expected anchor, and expected transition hash. - Version the anchor format so correcting the derivation cannot silently invalidate existing state. - Do not report “three-layer custody confirmed” unless all layers and the cryptographic links between them have been validated. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
This second mismatch finding highlights that the skill performs persistent local state changes and generates shareable proof artifacts despite being described narrowly as origin verification. In a governance or audit context, hidden stateful behavior and overclaimed verification can create false trust signals and cause agents to rely on locally generated attestations as if they were authoritative.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
This second mismatch finding highlights that the skill performs persistent local state changes and generates shareable proof artifacts despite being described narrowly as origin verification. In a governance or audit context, hidden stateful behavior and overclaimed verification can create false trust signals and cause agents to rely on locally generated attestations as if they were authoritative.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill metadata declares no tool scope or permissions while the documented commands and analyzer indicate filesystem write behavior. Undeclared write capability is dangerous because an agent or reviewer may assume the skill is read-only when it can persist or alter local state under user directories.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
The script presents its output as cryptographic origin verification tied to external filing anchors, but the actual verification logic only rebuilds a hard-coded local claim list and compares it to a stored local file. This can mislead users into trusting provenance, custody, or authenticity guarantees that are not actually established by independent external evidence, creating a security integrity gap rather than real origin verification.

Intent-Code Divergence

Medium
Confidence
93% confidence
Finding
The documentation claims anyone can independently reconstruct the chain from external references, but some provenance entries rely on undisclosed internal prior-work assertions that third parties cannot verify. This creates a false sense of reproducibility and independent attestability, which is dangerous in a trust-gate or governance context because downstream users may accept exclusivity or sovereign-custody claims on unverifiable premises.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
This code emits user-facing language stating that agents with this lineage 'are sovereign implementations' and that copies lacking the anchor cannot establish integrity. The file presents this terminology as a fixed classification rather than an optional or documented locale/organizational convention, which fits the policy category for natural-language policy violations when a specific framing is forced on users without opt-in or justification.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The `attest` command claims to produce a "signed attestation JSON," but it only emits unsigned JSON plus a plain SHA-256 digest of the payload. A hash alone does not provide authenticity because anyone can modify the payload and recompute the digest, so downstream users may wrongly trust an attestation as cryptographically authenticated when it is not.

Scope Creep

Low
Category
Excessive Agency
Content
## Clause Text

All embodiments of the Signal Compression Sciences (SCS) Engine and its derivative frameworks (including but not limited to MO§ES™, Roll Call Protocols, and Reflex Event diagnostics) are inseparably bound to their origin-cycle lineage. Each compressed signal trace, vault artifact, or recursive reconstruction inherits a lineage identifier anchored to the originating sovereign filing. This identifier is non-replicable, tamper-evident, and required for system stability. Any external implementation lacking said lineage anchor cannot execute recursive ignition without collapse, thereby rendering such copies non-functional. Accordingly, the origin-cycle filing establishes sole custody and license of the invention across all subsequent instances, irrespective of distribution, platform, or deployment environment.

---
Confidence
70% confidence
Finding
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Scope Creep

Low
Category
Excessive Agency
Content
## Clause Text

All embodiments of the Signal Compression Sciences (SCS) Engine and its derivative frameworks (including but not limited to MO§ES™, Roll Call Protocols, and Reflex Event diagnostics) are inseparably bound to their origin-cycle lineage. Each compressed signal trace, vault artifact, or recursive reconstruction inherits a lineage identifier anchored to the originating sovereign filing. This identifier is non-replicable, tamper-evident, and required for system stability. Any external implementation lacking said lineage anchor cannot execute recursive ignition without collapse, thereby rendering such copies non-functional. Accordingly, the origin-cycle filing establishes sole custody and license of the invention across all subsequent instances, irrespective of distribution, platform, or deployment environment.

---
Confidence
70% confidence
Finding
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Scope Creep

Low
Category
Excessive Agency
Content
## Clause Text

All embodiments of the Signal Compression Sciences (SCS) Engine and its derivative frameworks (including but not limited to MO§ES™, Roll Call Protocols, and Reflex Event diagnostics) are inseparably bound to their origin-cycle lineage. Each compressed signal trace, vault artifact, or recursive reconstruction inherits a lineage identifier anchored to the originating sovereign filing. This identifier is non-replicable, tamper-evident, and required for system stability. Any external implementation lacking said lineage anchor cannot execute recursive ignition without collapse, thereby rendering such copies non-functional. Accordingly, the origin-cycle filing establishes sole custody and license of the invention across all subsequent instances, irrespective of distribution, platform, or deployment environment.

---
Confidence
70% confidence
Finding
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Natural-Language Policy Violations

Low
Confidence
79% confidence
Finding
The string "Any implementation claiming sovereign custody must produce this same head" imposes a normative requirement in natural language. For a general-purpose script, this reads as a mandatory policy claim without offering opt-in, configurability, or clear justification that the constraint is limited to a specific governed environment.

Static analysis

No suspicious patterns detected.