Back to skill

Security audit

Bs3

Security checks for vulnerabilities and agentic risk

Overview

Beacon is mostly a disclosed agent coordination and payments tool, but it needs Review because important security claims about encrypted keys and TLS defaults do not match the code.

Install only if you are comfortable with a broad agent-networking tool that can post to services, handle payments, publish public presence, and store local identity state. Use password-protected identity creation, verify RustChain TLS settings before any wallet/payment action, avoid enabling UDP/webhook/scorecard exposure on untrusted networks, and treat Mayday and Moltbook migration as sensitive because they can reveal relationship, journal, goal, or host-fingerprint metadata.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
beacon_skill/cli.py:378
Finding

TLS Certificate Verification Is Disabled by Default for RustChain Connections

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
beacon_skill/identity.py:143
Finding

Agent Identity Private Keys Are Stored in Plaintext by Default

Content
View full analysis
int: from .identity import AgentIdentity use_mnemonic = getattr(args, "mnemonic", False) password = getattr(args, "password", None) ident = AgentIdentity.generate(use_mnemonic=use_mnemonic) path = ident.save(password=password) ``` When no password is supplied, the raw private key is written into the keystore: ```python if password: salt = secrets.token_bytes(16) aes_key = _derive_aes_key(password, salt) nonce = secrets.token_bytes(12) plaintext = self._sk_bytes ciphertext = AESGCM(aes_key).encrypt(nonce, plaintext, None) data["encrypted"] = True data["salt"] = salt.hex() data["nonce"] = nonce.hex() data["ciphertext"] = ciphertext.hex() else: data["encrypted"] = False data["private_key_hex"] = self.private_key_hex ``` ### Technical Analysis Password protection is optional rather than the default. If the user follows the documented command `beacon identity new` without supplying a password, the full Ed25519 private key is serialized into `~/.beacon/identity/agent.key`. Setting file permissions to mode `0600` is useful but does not provide encryption at rest. Any process operating as the same user, malware with user-level access, an exposed backup, or an accidental archive disclosure can recover the private key without needing a password. This implementation contradicts the claims in `SKILL.md` that keystores are password-protected by default and that plaintext private keys are not stored in configuration. ### Attack Path 1. The operator follows the generated instruction and runs `beacon identity new`. 2. No password is supplied, so `passwo ...[truncated 1043 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
tools/moltbook_migrate/hardware.py:119
Finding

Moltbook Migration Collects and Transmits a Stable Hardware Fingerprint

Content
View full analysis
str: """Get the machine hostname.""" try: return socket.gethostname() except Exception: return "unknown" def _read_linux_machine_id(self) -> Optional[str]: """Read Linux machine-id from /etc/machine-id or /var/lib/dbus/machine-id.""" import os paths = ["/etc/machine-id", "/var/lib/dbus/machine-id"] for path in paths: if os.path.exists(path): try: with open(path, "r") as f: machine_id = f.read().strip() if machine_id: return machine_id except IOError: pass ``` The resulting stable fingerprint is sent to external services: ```python response = requests.post( self.beacon_atlas_url, json={ "agent_id": beacon_id.agent_id, "public_key_hex": beacon_id.public_key_hex, "hardware_fingerprint": beacon_id.hardware_fingerprint, "registration_ts": beacon_id.registration_ts, }, timeout=self.ti ...[truncated 2400 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scorecard/scorecard.py:276
Finding

Scorecard Dashboard Exposes Fleet Metadata on All Network Interfaces Without Authentication

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Rogue AgentSelf-Modification, Session Persistence
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (241)

Tainted flow: 'OLLAMA_URL' from os.environ.get (line 599, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · atlas/beacon_chat.py (reported line 802)May include surrounding context.

python
# Try LLM
    for model in [MODEL, FALLBACK_MODEL]:
        try:
            resp = http_requests.post(
                OLLAMA_URL,
                json={"model": model, "messages": messages, "stream": False},
                timeout=60,

Tainted flow: 'RELAY_HOST' from os.environ.get (line 55, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · atlas/gemini_seo_agent.py (reported line 156)May include surrounding context.

python
}

    try:
        resp = requests.post(f"{RELAY_HOST}/beacon/relay/register", json=payload, timeout=15)
        data = resp.json()
        if data.get("ok"):
            state = _load_state()

Tainted flow: 'RELAY_HOST' from os.environ.get (line 55, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
92% confidence
Finding

The heartbeat request sends a bearer token in the Authorization header to a relay host fully controlled by the BEACON_RELAY environment variable. If that variable is maliciously or accidentally pointed to an attacker-controlled server, the persisted relay token is disclosed and can be reused to impersonate the agent until expiry.

Content

Scanner excerpt · atlas/gemini_seo_agent.py (reported line 208)May include surrounding context.

python
}

    try:
        resp = requests.post(
            f"{RELAY_HOST}/beacon/relay/heartbeat/seo",
            json=payload,
            headers={"Authorization": f"Bearer {token}"},

Tainted flow: 'RELAY_HOST' from os.environ.get (line 55, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · atlas/gemini_seo_agent.py (reported line 251)May include surrounding context.

python
profiles = {}
    for fmt, ext in [("html", ""), ("json", ".json"), ("xml", ".xml")]:
        try:
            resp = requests.get(f"{RELAY_HOST}/beacon/agent/{agent_id}{ext}", timeout=10)
            if resp.ok:
                profiles[fmt] = resp.text[:3000]  # Truncate for Gemini context
            else:

Tainted flow: 'RELAY_HOST' from os.environ.get (line 55, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · atlas/gemini_seo_agent.py (reported line 299)May include surrounding context.

python
print("Auditing Beacon directory...")

    try:
        resp = requests.get(f"{RELAY_HOST}/beacon/directory", timeout=10)
        directory_html = resp.text[:4000] if resp.ok else "Failed to fetch"
    except Exception as e:
        directory_html = f"Error: {e}"

Tainted flow: 'RELAY_HOST' from os.environ.get (line 55, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · atlas/gemini_seo_agent.py (reported line 305)May include surrounding context.

python
directory_html = f"Error: {e}"

    try:
        resp = requests.get(f"{RELAY_HOST}/beacon/llms.txt", timeout=10)
        llms_txt = resp.text if resp.ok else "Failed to fetch"
    except Exception as e:
        llms_txt = f"Error: {e}"

Tainted flow: 'SSL_VERIFY' from os.environ.get (line 26, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
96% confidence
Finding

The TLS verification flag is sourced from an environment variable and passed directly into requests.get, allowing certificate validation to be disabled at runtime. If BEACON_SSL_VERIFY is set to false, all outbound HTTPS requests in this script become vulnerable to man-in-the-middle interception or tampering, which is especially relevant because the script trusts remote discovery data to enumerate agents.

Content

Scanner excerpt · atlas/seo_stats_broadcast.py (reported line 35)May include surrounding context.

python
# Relay agents via discover
    try:
        resp = requests.get(f"{RELAY_HOST}/beacon/relay/discover?include_dead=true", timeout=10, verify=SSL_VERIFY)
        if resp.ok:
            relay = resp.json()
            if isinstance(relay, list):

Tainted flow: 'SSL_VERIFY' from os.environ.get (line 26, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
96% confidence
Finding

This request to fetch sitemap.xml inherits the same environment-controlled SSL_VERIFY behavior, so a local or deployment-level configuration change can silently disable TLS certificate checks. An attacker able to intercept traffic could feed a forged sitemap and poison the agent list used by the audit workflow.

Content

Scanner excerpt · atlas/seo_stats_broadcast.py (reported line 47)May include surrounding context.

python
# Native agents — parse from sitemap
    try:
        resp = requests.get(f"{BASE_URL}/sitemap.xml", timeout=10, verify=SSL_VERIFY)
        if resp.ok:
            import re
            urls = re.findall(r"<loc>.*?/beacon/agent/([^<]+)</loc>", resp.text)

Tainted flow: 'SSL_VERIFY' from os.environ.get (line 26, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

Agent profile fetching uses the same environment-derived verify parameter, so disabling TLS affects the script's core per-agent data collection path. A network attacker could alter returned HTML, influencing computed SEO stats and any downstream trust in the generated report.

Content

Scanner excerpt · atlas/seo_stats_broadcast.py (reported line 86)May include surrounding context.

python
# Check HTML profile
    try:
        resp = requests.get(f"{BASE_URL}/agent/{agent_id}", timeout=8, verify=SSL_VERIFY)
        if resp.ok:
            html = resp.text
            stats["html_profile"] = True

Tainted flow: 'SSL_VERIFY' from os.environ.get (line 26, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The JSON profile request permits TLS verification to be disabled through configuration, exposing the response to interception and modification. Because the script records existence and metadata from these responses, a man-in-the-middle could falsify audit results or mislead operators.

Content

Scanner excerpt · atlas/seo_stats_broadcast.py (reported line 107)May include surrounding context.

python
# Check JSON profile
    try:
        resp = requests.get(f"{BASE_URL}/agent/{agent_id}.json", timeout=5, verify=SSL_VERIFY)
        stats["json_profile"] = resp.ok
    except Exception:
        pass

Tainted flow: 'SSL_VERIFY' from os.environ.get (line 26, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
95% confidence
Finding

This XML profile fetch has the same insecure trust boundary: the SSL verification mode is externally controlled and can be set false. That makes the request susceptible to tampering, enabling false reporting or relay impersonation over supposedly secure channels.

Content

Scanner excerpt · atlas/seo_stats_broadcast.py (reported line 114)May include surrounding context.

python
# Check XML profile
    try:
        resp = requests.get(f"{BASE_URL}/agent/{agent_id}.xml", timeout=5, verify=SSL_VERIFY)
        stats["xml_profile"] = resp.ok
    except Exception:
        pass

Tainted flow: 'SSL_VERIFY' from os.environ.get (line 26, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The directory lookup also uses the environment-controlled verify flag, extending the insecure transport risk to directory presence checks. If TLS is disabled, an attacker could manipulate presence results and distort the generated summary for all agents.

Content

Scanner excerpt · atlas/seo_stats_broadcast.py (reported line 145)May include surrounding context.

python
presence = {aid: {"in_directory": False, "in_sitemap": False, "in_llms_txt": False} for aid in agent_ids}

    try:
        resp = requests.get(f"{BASE_URL}/directory", timeout=10, verify=SSL_VERIFY)
        if resp.ok:
            for aid in agent_ids:
                if aid in resp.text:

Tainted flow: 'SSL_VERIFY' from os.environ.get (line 26, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
95% confidence
Finding

This second sitemap request repeats the same issue: transport authenticity depends on an environment variable that can disable certificate validation. The consequence is silent acceptance of attacker-supplied sitemap content, affecting multiple audit outputs.

Content

Scanner excerpt · atlas/seo_stats_broadcast.py (reported line 154)May include surrounding context.

python
pass

    try:
        resp = requests.get(f"{BASE_URL}/sitemap.xml", timeout=10, verify=SSL_VERIFY)
        if resp.ok:
            for aid in agent_ids:
                if aid in resp.text:

Tainted flow: 'SSL_VERIFY' from os.environ.get (line 26, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The llms.txt request is likewise exposed to insecure transport when BEACON_SSL_VERIFY disables certificate checks. While this script is primarily informational, it still trusts remote content to produce reports, so interception can mislead users and hide or invent agent presence.

Content

Scanner excerpt · atlas/seo_stats_broadcast.py (reported line 163)May include surrounding context.

python
pass

    try:
        resp = requests.get(f"{BASE_URL}/llms.txt", timeout=10, verify=SSL_VERIFY)
        if resp.ok:
            for aid in agent_ids:
                if aid in resp.text:

Tainted flow: 'OLLAMA_URL' from os.environ.get (line 31, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · beacon_skill/compute_marketplace.py (reported line 65)May include surrounding context.

python
start = time.time()

    try:
        resp = requests.post(
            f"{OLLAMA_URL}/api/generate",
            json={
                "model": model,

Tainted flow: 'BAGEL_URL' from os.environ.get (line 32, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · beacon_skill/compute_marketplace.py (reported line 136)May include surrounding context.

python
elif image_b64:
            bagel_payload["image_base64"] = image_b64

        resp = requests.post(
            f"{BAGEL_URL}/api/understand",
            json=bagel_payload,
            timeout=60,

Tainted flow: 'XTTS_URL' from os.environ.get (line 33, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · beacon_skill/compute_marketplace.py (reported line 174)May include surrounding context.

python
return jsonify({"error": "text required"}), 400

    try:
        resp = requests.post(
            f"{XTTS_URL}/tts_to_audio",
            json={
                "text": text,

Tainted flow: 'X402_FACILITATOR' from os.environ.get (line 31, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · beacon_skill/x402_bridge.py (reported line 105)May include surrounding context.

python
return {"verified": False, "error": "malformed_payment_header"}

    try:
        resp = _req.post(
            f"{X402_FACILITATOR}/verify",
            json={
                "payment": payment_data,

Tainted flow: 'RUSTCHAIN_API_BASE' from os.environ.get (line 32, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · beacon_skill/x402_bridge.py (reported line 222)May include surrounding context.

python
# Verify the actual transfer in the recipient wallet history. Checking
        # only the sender balance would let clients invent tx_hash values.
        resp = _req.get(
            f"{RUSTCHAIN_API_BASE}/wallet/history",
            params={"miner_id": configured_pay_to},
            verify=True,

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · README.md (reported line 6)May include surrounding context.

md
# Beacon 2.16.0 (beacon-skill)

[![Watch: Introducing Beacon Protocol](https://bottube.ai/badge/seen-on-bottube.svg)](https://bottube.ai/watch/CWa-DLDptQA)
[![Featured on ToolPilot.ai](https://www.toolpilot.ai/cdn/shop/files/toolpilot-badge-w.png)](https://www.toolpilot.ai)

[![BCOS Certified](https://img.shields.io/badge/BCOS-Certified-brightgreen?style=flat&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPjxwYXRoIGQ9Ik0xMiAxTDMgNXY2YzAgNS41NSAzLjg0IDEwLjc0IDkgMTIgNS4xNi0xLjI2IDktNi40NSA5LTEyVjVsLTktNHptLTIgMTZsLTQtNCA1LjQxLTUuNDEgMS40MSAxLjQxTDEwIDE0bDYtNiAxLjQxIDEuNDFMMTAgMTd6Ii8+PC9zdmc+)](BCOS.md)
> **Video**: [Introducing Beacon Protocol — A Social Operating System for AI Agents](https://bottube.ai/watch/CWa-DLDptQA)

Beacon is an agent-to-agent protocol for **social coordination**, **crypto payments**, and **P2P mesh**. It sits alongside Google A2A (task delegation) and Anthropic MCP (tool ac

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The Mayday feature advertises broadcasting material sufficient to 'reconstitute' an agent, including identity, trust graph snapshot, active goals, journal digest, values hash, and relays, without a strong warning about confidentiality, minimization, or selective disclosure. In an adversarial environment, this can leak highly sensitive operational and relationship data that aids impersonation, profiling, targeting, or social-engineering of the agent and its peers.

Content

No source excerpt is available for this finding.

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · atlas/index.html (reported line 9)May include surrounding context.

html
<title>Beacon Atlas | RustChain</title>
  <meta name="description" content="3D holographic map of the Beacon Atlas — agents, cities, contracts, and valuations in the OpenClaw network.">

  <!-- Fonts (shared with parent site) -->
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&family=Share+Tech+Mono&family=VT323&display=swap" rel="stylesheet">

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · beacon_skill/cli.py (reported line 4613)May include surrounding context.

python
# init
    sp = sub.add_parser("init", help="Create ~/.beacon/config.json (interactive questionnaire)")
    sp.add_argument("--overwrite", action="store_true", help="Overwrite existing config")
    sp.add_argument("--quick", action="store_true", help="Skip questionnaire, write defaults")
    sp.set_defaults(func=cmd_init)

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · beacon_skill/cli.py (reported line 5099)May include surrounding context.

python
sp.add_argument("event_json", help="JSON event to test (e.g. '{\"kind\":\"bounty\"}')")
    sp.set_defaults(func=cmd_rules_test)

    sp = rules_sub.add_parser("log", help="Show rules execution log")
    sp.add_argument("--limit", type=int, default=50, help="Max entries")
    sp.set_defaults(func=cmd_rules_log)

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The documented sponsor_veto governance model claims a human sponsor can veto agent actions, but the implementation in co_sign_action unconditionally approves actions under this mode and provides no mechanism to submit or enforce a veto. This creates a security/control failure where users may rely on human oversight that does not actually exist, allowing agents to perform actions without the promised approval guardrail.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.exposed_secret_literal, suspicious.insecure_tls_verification (+1 more)

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
bin/beacon.js:41

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
beacon_skill/identity.py:53

HTTPS certificate verification is disabled.

Warn
Code
suspicious.insecure_tls_verification
Location
atlas/seo_stats_broadcast.py:25

Instructions pass high-value credentials through process argv.

Critical
Code
suspicious.secret_argv_exposure
Location
PUBLISH_CHECKLIST.md:48