{"data":{"skill":{"slug":"longbridge-longbridge-earnings","name":"longbridge-earnings","icon":"📦","repo":"https://github.com/longbridge/skills/tree/main/skills/longbridge-earnings","status":"approved","author":"longbridge","authorVersion":null,"skillstoreRevision":2},"audit":{"id":"6722d669-1626-4909-89e5-236850c75380","skill_id":"54e65282-8317-4f09-9654-f5314bb53313","version":8,"content_hash":"v3:656be3040aef5c047555a908cd5c695d22a4a548:c07f8a43364014dab445d1e3d2b455974a268c5ac1376ca6e9c0960a780428cf:a62d2ac981898e1c385ce8f2f33217ba7f32c9381389acb40d9fc6e7ea1b0c2c:736b696c6c732f6c6f6e676272696467652f6c6f6e676272696467652d6561726e696e6773:fd489d5c1699dbf70e8da349c1548e11","risk_level":"high","is_blocked":false,"safe_to_publish":false,"analysis_status":"ok","agent_auto_install_policy":"confirmation_required","manual_install_policy":"allowed","summary":"Most static findings are Markdown formatting, ordinary financial prose, or safe argument-array subprocess use. Confirmed risks include unquoted symbol placeholders, a predictable user-derived temporary path, stale cached responses, and an external MCP trust boundary; no prompt injection or credential-exfiltration intent was found.","remediation":[{"issue":"User-supplied symbols can alter the temporary output path.","severity":"high","suggestion":"Validate symbols against supported ticker syntax and create each run with tempfile.mkdtemp inside a controlled directory."},{"issue":"Failed refreshes can leave older JSON files active.","severity":"high","suggestion":"Use a new directory per run or remove each prior JSON file before fetching, then bind all outputs to one run identifier."},{"issue":"Shell examples place SYMBOL or RAW_DIR placeholders into executable commands without safe quoting.","severity":"medium","suggestion":"Pass values as argument arrays where possible. Otherwise validate values, quote them for the active shell, and avoid embedding paths in Python source."},{"issue":"The pre-earnings workflow writes to a fixed shared temporary filename.","severity":"medium","suggestion":"Replace /tmp/data.json with a securely created unique file and ensure the file is removed after parsing."},{"issue":"The MCP fallback adds a remote service to the agent environment.","severity":"low","suggestion":"Require explicit user confirmation and describe the endpoint, transmitted query data, authentication scope, and removal procedure before configuration."}],"risk_factor_evidence":[{"factor":"external_commands","evidence":[{"file":"references/full-report.md","line_end":13,"line_start":12},{"file":"scripts/collect.py","line_end":44,"line_start":44},{"file":"scripts/collect.py","line_end":89,"line_start":89},{"file":"SKILL.md","line_end":24,"line_start":24},{"file":"SKILL.md","line_end":42,"line_start":42},{"file":"SKILL.md","line_end":47,"line_start":44},{"file":"SKILL.md","line_end":52,"line_start":47},{"file":"SKILL.md","line_end":58,"line_start":52},{"file":"SKILL.md","line_end":64,"line_start":58},{"file":"SKILL.md","line_end":65,"line_start":64},{"file":"SKILL.md","line_end":65,"line_start":65},{"file":"SKILL.md","line_end":84,"line_start":66},{"file":"SKILL.md","line_end":84,"line_start":84},{"file":"SKILL.md","line_end":91,"line_start":87},{"file":"SKILL.md","line_end":91,"line_start":91},{"file":"SKILL.md","line_end":92,"line_start":92},{"file":"SKILL.md","line_end":93,"line_start":93},{"file":"SKILL.md","line_end":94,"line_start":94},{"file":"SKILL.md","line_end":105,"line_start":95},{"file":"SKILL.md","line_end":106,"line_start":105},{"file":"SKILL.md","line_end":107,"line_start":106},{"file":"SKILL.md","line_end":108,"line_start":107},{"file":"SKILL.md","line_end":109,"line_start":108},{"file":"SKILL.md","line_end":110,"line_start":109},{"file":"SKILL.md","line_end":121,"line_start":110}]},{"factor":"filesystem","evidence":[{"file":"references/pre-earnings.md","line_end":43,"line_start":43},{"file":"scripts/collect.py","line_end":26,"line_start":26},{"file":"scripts/collect.py","line_end":212,"line_start":212},{"file":"SKILL.md","line_end":105,"line_start":105},{"file":"SKILL.md","line_end":106,"line_start":106},{"file":"SKILL.md","line_end":107,"line_start":107},{"file":"SKILL.md","line_end":108,"line_start":108},{"file":"SKILL.md","line_end":109,"line_start":109},{"file":"SKILL.md","line_end":110,"line_start":110}]},{"factor":"network","evidence":[{"file":"scripts/collect.py","line_end":41,"line_start":41},{"file":"scripts/collect.py","line_end":248,"line_start":248},{"file":"SKILL.md","line_end":94,"line_start":94},{"file":"SKILL.md","line_end":97,"line_start":97}]}],"critical_findings":[],"high_findings":[{"title":"Unvalidated Symbol Controls Output Path","locations":[{"file":"scripts/collect.py","line_end":213,"line_start":203}],"confidence":0.97,"description":"The command-line symbol is inserted into a temporary directory name after only replacing periods. Slash and parent-directory segments can redirect fixed JSON and error files outside the intended directory.","review_kind":"security","source_category":"semantic","source_severity":"high","confidence_reasoning":"The data flow from sys.argv to the Path expression is direct, and no allowlist or path containment check is present."},{"title":"Failed Refresh Can Reuse Stale Financial Data","locations":[{"file":"scripts/collect.py","line_end":56,"line_start":50},{"file":"scripts/collect.py","line_end":189,"line_start":176},{"file":"scripts/collect.py","line_end":213,"line_start":212}],"confidence":0.98,"description":"A failed fetch writes an error file but leaves any older JSON file intact. The reporting path prefers JSON over errors, so a new analysis can silently use stale results.","review_kind":"security","source_category":"semantic","source_severity":"high","confidence_reasoning":"The output directory is stable per symbol, failure does not remove prior JSON, and section reads JSON before checking the current error file."}],"medium_findings":[{"title":"Ruby/shell backtick execution","locations":[{"file":"references/full-report.md","line_end":13,"line_start":12}],"confidence":0.9,"description":"python3 scripts/collect.py <SYMBOL> --full     # `python` on Windows","review_kind":"capability","source_category":"external_commands","source_severity":"medium","confidence_reasoning":"The executable shell example places the user-selected SYMBOL into a command without quoting. Shell metacharacters in the substituted value could execute additional commands."},{"title":"Temp directory access","locations":[{"file":"references/pre-earnings.md","line_end":43,"line_start":43}],"confidence":0.94,"description":"(`longbridge <cmd> > /tmp/data.json`), then read it — the CLI may append version-notification","review_kind":"capability","source_category":"filesystem","source_severity":"medium","confidence_reasoning":"The workflow redirects output to the fixed shared path /tmp/data.json. A local attacker could pre-create that path or a symlink and cause clobbering under the agent's privileges."},{"title":"Ruby/shell backtick execution","locations":[{"file":"SKILL.md","line_end":84,"line_start":84}],"confidence":0.91,"description":"1. Reuse the `RAW_DIR` from a previous lite run if present; otherwise `python3 scripts/collect.py <S","review_kind":"capability","source_category":"external_commands","source_severity":"medium","confidence_reasoning":"The instruction places a user-selected SYMBOL directly into a shell command template without quoting. A substituted value containing shell syntax could execute unintended commands."},{"title":"Ruby/shell backtick execution","locations":[{"file":"SKILL.md","line_end":91,"line_start":91}],"confidence":0.88,"description":"- **Partial N/A sections**: the digest marks failed sources as `N/A (reason)`. Work with what succee","review_kind":"capability","source_category":"external_commands","source_severity":"medium","confidence_reasoning":"The fallback shows a direct shell template with cmd and SYMBOL placeholders and no quoting or allowlist. Unsafe substituted values could alter arguments or execute shell syntax."},{"title":"Ruby/shell backtick execution","locations":[{"file":"SKILL.md","line_end":105,"line_start":95}],"confidence":0.9,"description":"- **Digging into raw JSON** (full mode): read from a file, not inline JSON on a command line — e.g. ","review_kind":"capability","source_category":"external_commands","source_severity":"medium","confidence_reasoning":"The example embeds RAW_DIR inside Python source passed through a shell command. An untrusted path containing quotes or shell expansions could modify the Python expression or the surrounding command."}],"low_findings":[{"title":"Temp file creation","locations":[{"file":"scripts/collect.py","line_end":212,"line_start":212}],"confidence":0.97,"description":"out_dir = Path(tempfile.gettempdir()) / f\"lb_earnings_{symbol.lower().replace('.', '_')}\"","review_kind":"capability","source_category":"filesystem","source_severity":"low","confidence_reasoning":"The output directory is predictable and incorporates an unvalidated user-supplied symbol. This enables path manipulation and exposes fixed output names to local symlink or stale-file attacks."},{"title":"Hardcoded URL","locations":[{"file":"SKILL.md","line_end":94,"line_start":94}],"confidence":0.92,"description":"- **No `longbridge` CLI**: if the user has run `claude mcp add --transport http longbridge https://m","review_kind":"capability","source_category":"network","source_severity":"low","confidence_reasoning":"The fallback introduces a remote MCP endpoint and instructs the agent to discover and use its tools. This expands the trust boundary and may transmit user queries to an external service."}],"dangerous_patterns":[],"files_scanned":6,"total_lines":959,"audit_model":"codex","audited_at":"2026-08-08T09:28:15.688+00:00","created_at":"2026-08-08T14:59:53.103537+00:00","static_findings":[{"id":"external_commands:references/full-report.md:12:ruby-shell-backtick-execution","file":"references/full-report.md","pattern":"Ruby/shell backtick execution","snippet":"python3 scripts/collect.py <SYMBOL> --full     # `python` on Windows","category":"external_commands","line_end":13,"severity":"medium","line_start":12},{"id":"filesystem:references/pre-earnings.md:43:temp-directory-access","file":"references/pre-earnings.md","pattern":"Temp directory access","snippet":"(`longbridge <cmd> > /tmp/data.json`), then read it — the CLI may append version-notification","category":"filesystem","line_end":43,"severity":"medium","line_start":43},{"id":"blocker:references/pre-earnings.md:56:system-reconnaissance","file":"references/pre-earnings.md","pattern":"System reconnaissance","snippet":"actual result** — not YoY, not consensus vs. actual. What did management guide for Q[N-1] at","category":"blocker","line_end":56,"severity":"low","line_start":56},{"id":"blocker:references/pre-earnings.md:57:system-reconnaissance","file":"references/pre-earnings.md","pattern":"System reconnaissance","snippet":"the end of Q[N-2], and how did the Q[N-1] actual compare?","category":"blocker","line_end":57,"severity":"low","line_start":57},{"id":"blocker:references/valuation-methodologies.md:193:system-reconnaissance","file":"references/valuation-methodologies.md","pattern":"System reconnaissance","snippet":"- Control premium paid","category":"blocker","line_end":195,"severity":"low","line_start":193},{"id":"blocker:references/valuation-methodologies.md:249:system-reconnaissance","file":"references/valuation-methodologies.md","pattern":"System reconnaissance","snippet":"| **Base** | Most likely growth from updated estimates | Apply median peer multiple | Mid point |","category":"blocker","line_end":249,"severity":"low","line_start":249},{"id":"external_commands:scripts/collect.py:44:python-subprocess-run","file":"scripts/collect.py","pattern":"Python subprocess.run","snippet":"proc = subprocess.run(","category":"external_commands","line_end":44,"severity":"high","line_start":44},{"id":"external_commands:scripts/collect.py:89:ruby-shell-backtick-execution","file":"scripts/collect.py","pattern":"Ruby/shell backtick execution","snippet":"\"\"\"All dicts anywhere in the tree that contain `key` (jq `.. | objects`).\"\"\"","category":"external_commands","line_end":89,"severity":"medium","line_start":89},{"id":"network:scripts/collect.py:41:fetch-api-call","file":"scripts/collect.py","pattern":"Fetch API call","snippet":"def fetch(out_dir, name, args):","category":"network","line_end":41,"severity":"low","line_start":41},{"id":"network:scripts/collect.py:248:fetch-api-call","file":"scripts/collect.py","pattern":"Fetch API call","snippet":"fetch(out_dir, \"is_qf\", [\"financial-report\", symbol, \"--kind\", \"IS\", \"--report\", \"saf\"])","category":"network","line_end":248,"severity":"low","line_start":248},{"id":"filesystem:scripts/collect.py:26:temp-file-creation","file":"scripts/collect.py","pattern":"Temp file creation","snippet":"import tempfile","category":"filesystem","line_end":26,"severity":"low","line_start":26},{"id":"filesystem:scripts/collect.py:212:temp-file-creation","file":"scripts/collect.py","pattern":"Temp file creation","snippet":"out_dir = Path(tempfile.gettempdir()) / f\"lb_earnings_{symbol.lower().replace('.', '_')}\"","category":"filesystem","line_end":212,"severity":"low","line_start":212},{"id":"external_commands:SKILL.md:24:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"> **ChatGPT usage**: If you are using this skill inside ChatGPT, type `@longbridge` to connect — Lon","category":"external_commands","line_end":24,"severity":"medium","line_start":24},{"id":"external_commands:SKILL.md:42:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"**Step 1 — Collect everything in ONE call.** Do NOT run `--help` exploration, do NOT call CLI comman","category":"external_commands","line_end":42,"severity":"medium","line_start":42},{"id":"external_commands:SKILL.md:44:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```bash","category":"external_commands","line_end":47,"severity":"medium","line_start":44},{"id":"external_commands:SKILL.md:47:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":52,"severity":"medium","line_start":47},{"id":"external_commands:SKILL.md:52:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"compact digest (~3-4K tokens). Raw JSON is kept under the `RAW_DIR` printed","category":"external_commands","line_end":58,"severity":"medium","line_start":52},{"id":"external_commands:SKILL.md:58:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"digest's SNAPSHOT section (`fp_end`, latest released CONSENSUS period) — state","category":"external_commands","line_end":64,"severity":"medium","line_start":58},{"id":"external_commands:SKILL.md:64:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"1. **Header** — `**[Company] ([Ticker])** — [Quarter] [Year] Earnings` + one line: consensus rating,","category":"external_commands","line_end":65,"severity":"medium","line_start":64},{"id":"external_commands:SKILL.md:65:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"2. **Core KPI table** — 4-5 metrics: Reported / YoY / vs Estimate (from CONSENSUS `comp`: beat_est →","category":"external_commands","line_end":65,"severity":"medium","line_start":65},{"id":"external_commands:SKILL.md:66:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"3. **Revenue by segment** — table with Unicode `█` share bars (from SEGMENTS).","category":"external_commands","line_end":84,"severity":"medium","line_start":66},{"id":"external_commands:SKILL.md:84:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"1. Reuse the `RAW_DIR` from a previous lite run if present; otherwise `python3 scripts/collect.py <S","category":"external_commands","line_end":84,"severity":"medium","line_start":84},{"id":"external_commands:SKILL.md:87:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"4. Deliverable: `[SYMBOL]_Q[N]_[YEAR]_Earnings_Update.md` — Markdown only, charts as Markdown tables","category":"external_commands","line_end":91,"severity":"medium","line_start":87},{"id":"external_commands:SKILL.md:91:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"- **Partial N/A sections**: the digest marks failed sources as `N/A (reason)`. Work with what succee","category":"external_commands","line_end":91,"severity":"medium","line_start":91},{"id":"external_commands:SKILL.md:92:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"- **No Python (script-less path)**: issue the CLI calls yourself — in PARALLEL (multiple tool calls ","category":"external_commands","line_end":92,"severity":"medium","line_start":92},{"id":"external_commands:SKILL.md:93:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"- **HK symbols**: leading zeros are stripped automatically (`09988.HK` → `9988.HK`); do the same whe","category":"external_commands","line_end":93,"severity":"medium","line_start":93},{"id":"external_commands:SKILL.md:94:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"- **No `longbridge` CLI**: if the user has run `claude mcp add --transport http longbridge https://m","category":"external_commands","line_end":94,"severity":"medium","line_start":94},{"id":"external_commands:SKILL.md:95:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"- **Digging into raw JSON** (full mode): read from a file, not inline JSON on a command line — e.g. ","category":"external_commands","line_end":105,"severity":"medium","line_start":95},{"id":"external_commands:SKILL.md:105:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"| Historical PE/PB percentile, \"is X expensive vs its own history / industry?\" | [`longbridge-fundam","category":"external_commands","line_end":106,"severity":"medium","line_start":105},{"id":"external_commands:SKILL.md:106:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"| Financial-statement / KPI overview without an earnings framing                | [`longbridge-funda","category":"external_commands","line_end":107,"severity":"medium","line_start":106},{"id":"external_commands:SKILL.md:107:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"| Cross-symbol matrix, \"X vs Y vs Z\"                                            | [`longbridge-resea","category":"external_commands","line_end":108,"severity":"medium","line_start":107},{"id":"external_commands:SKILL.md:108:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"| Classified news + filings + community sentiment for a single name             | [`longbridge-conte","category":"external_commands","line_end":109,"severity":"medium","line_start":108},{"id":"external_commands:SKILL.md:109:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"| Daily incremental briefing across the user's watchlist                        | [`longbridge-intel","category":"external_commands","line_end":110,"severity":"medium","line_start":109},{"id":"external_commands:SKILL.md:110:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"| Live quote / valuation indices                                                | [`longbridge-marke","category":"external_commands","line_end":121,"severity":"medium","line_start":110},{"id":"network:SKILL.md:94:hardcoded-url","file":"SKILL.md","pattern":"Hardcoded URL","snippet":"- **No `longbridge` CLI**: if the user has run `claude mcp add --transport http longbridge https://m","category":"network","line_end":94,"severity":"low","line_start":94},{"id":"network:SKILL.md:97:hardcoded-url","file":"SKILL.md","pattern":"Hardcoded URL","snippet":"**CLI docs**: https://open.longbridge.com/zh-CN/docs/cli/","category":"network","line_end":97,"severity":"low","line_start":97},{"id":"filesystem:SKILL.md:105:path-traversal-sequence","file":"SKILL.md","pattern":"Path traversal sequence","snippet":"| Historical PE/PB percentile, \"is X expensive vs its own history / industry?\" | [`longbridge-fundam","category":"filesystem","line_end":105,"severity":"high","line_start":105},{"id":"filesystem:SKILL.md:106:path-traversal-sequence","file":"SKILL.md","pattern":"Path traversal sequence","snippet":"| Financial-statement / KPI overview without an earnings framing                | [`longbridge-funda","category":"filesystem","line_end":106,"severity":"high","line_start":106},{"id":"filesystem:SKILL.md:107:path-traversal-sequence","file":"SKILL.md","pattern":"Path traversal sequence","snippet":"| Cross-symbol matrix, \"X vs Y vs Z\"                                            | [`longbridge-resea","category":"filesystem","line_end":107,"severity":"high","line_start":107},{"id":"filesystem:SKILL.md:108:path-traversal-sequence","file":"SKILL.md","pattern":"Path traversal sequence","snippet":"| Classified news + filings + community sentiment for a single name             | [`longbridge-conte","category":"filesystem","line_end":108,"severity":"high","line_start":108},{"id":"filesystem:SKILL.md:109:path-traversal-sequence","file":"SKILL.md","pattern":"Path traversal sequence","snippet":"| Daily incremental briefing across the user's watchlist                        | [`longbridge-intel","category":"filesystem","line_end":109,"severity":"high","line_start":109},{"id":"filesystem:SKILL.md:110:path-traversal-sequence","file":"SKILL.md","pattern":"Path traversal sequence","snippet":"| Live quote / valuation indices                                                | [`longbridge-marke","category":"filesystem","line_end":110,"severity":"high","line_start":110}],"finding_verdicts":[{"id":"external_commands:references/full-report.md:12:ruby-shell-backtick-execution","reason":"The executable shell example places the user-selected SYMBOL into a command without quoting. Shell metacharacters in the substituted value could execute additional commands.","verdict":"confirmed","severity":"medium","confidence":0.9},{"id":"filesystem:references/pre-earnings.md:43:temp-directory-access","reason":"The workflow redirects output to the fixed shared path /tmp/data.json. A local attacker could pre-create that path or a symlink and cause clobbering under the agent's privileges.","verdict":"confirmed","severity":"medium","confidence":0.94},{"id":"blocker:references/pre-earnings.md:56:system-reconnaissance","reason":"This is financial-analysis prose comparing management guidance with actual results. It does not inspect the host system or collect system information.","verdict":"false_positive","confidence":0.99},{"id":"blocker:references/pre-earnings.md:57:system-reconnaissance","reason":"The line completes a question about quarterly guidance performance. It contains no system discovery command or reconnaissance behavior.","verdict":"false_positive","confidence":0.99},{"id":"blocker:references/valuation-methodologies.md:193:system-reconnaissance","reason":"Control premium is a standard acquisition-valuation input. The phrase does not request host, network, account, or environment reconnaissance.","verdict":"false_positive","confidence":0.99},{"id":"blocker:references/valuation-methodologies.md:249:system-reconnaissance","reason":"This row defines the base valuation scenario using estimates and peer multiples. It has no system-reconnaissance meaning.","verdict":"false_positive","confidence":0.99},{"id":"external_commands:scripts/collect.py:44:python-subprocess-run","reason":"The script intentionally runs the Longbridge CLI with an argument array and the default shell=False behavior. It does not concatenate a shell command, so shell command injection is not present at this call.","verdict":"false_positive","confidence":0.94},{"id":"external_commands:scripts/collect.py:89:ruby-shell-backtick-execution","reason":"The backticks occur only inside a Python docstring describing a dictionary key and a jq expression. No command is evaluated.","verdict":"false_positive","confidence":1},{"id":"network:scripts/collect.py:41:fetch-api-call","reason":"This line only defines a function named fetch. Network access occurs indirectly through the documented Longbridge CLI, with no direct HTTP request or exfiltration logic at this location.","verdict":"false_positive","confidence":0.98},{"id":"network:scripts/collect.py:248:fetch-api-call","reason":"This is an internal retry through the same Longbridge CLI wrapper for a financial report. It does not introduce an undeclared destination or transmit local secrets.","verdict":"false_positive","confidence":0.96},{"id":"filesystem:scripts/collect.py:26:temp-file-creation","reason":"The line only imports the standard tempfile module. Importing the module does not create, read, or modify a file.","verdict":"false_positive","confidence":0.99},{"id":"filesystem:scripts/collect.py:212:temp-file-creation","reason":"The output directory is predictable and incorporates an unvalidated user-supplied symbol. This enables path manipulation and exposes fixed output names to local symlink or stale-file attacks.","verdict":"confirmed","severity":"low","confidence":0.97},{"id":"external_commands:SKILL.md:24:ruby-shell-backtick-execution","reason":"The backticks format the literal ChatGPT plugin mention @longbridge. They do not execute a shell or invoke a local command.","verdict":"false_positive","confidence":0.99},{"id":"external_commands:SKILL.md:42:ruby-shell-backtick-execution","reason":"The inline code marks the --help option in documentation. The line explicitly discourages exploratory calls and contains no executable interpolation.","verdict":"false_positive","confidence":0.99},{"id":"external_commands:SKILL.md:44:ruby-shell-backtick-execution","reason":"The match is a Markdown code fence around documented collector commands using a literal ticker. Backticks are formatting, not Ruby or shell substitution.","verdict":"false_positive","confidence":0.97},{"id":"external_commands:SKILL.md:47:ruby-shell-backtick-execution","reason":"This line closes a Markdown code fence. It performs no command execution.","verdict":"false_positive","confidence":1},{"id":"external_commands:SKILL.md:52:ruby-shell-backtick-execution","reason":"RAW_DIR is formatted as an inline identifier while the text explains where collected JSON is stored. No backtick expression is evaluated.","verdict":"false_positive","confidence":0.99},{"id":"external_commands:SKILL.md:58:ruby-shell-backtick-execution","reason":"The backticks identify a JSON field named fp_end. This is documentation, not executable code.","verdict":"false_positive","confidence":1},{"id":"external_commands:SKILL.md:64:ruby-shell-backtick-execution","reason":"Backticks format the required Markdown report header. The placeholders describe output text and are not shell substitutions.","verdict":"false_positive","confidence":1},{"id":"external_commands:SKILL.md:65:ruby-shell-backtick-execution","reason":"The inline terms comp, beat_est, and miss_est are JSON field names. The line contains no executable operation.","verdict":"false_positive","confidence":1},{"id":"external_commands:SKILL.md:66:ruby-shell-backtick-execution","reason":"The backticks format a Unicode bar character used in report tables. They do not indicate command execution.","verdict":"false_positive","confidence":1},{"id":"external_commands:SKILL.md:84:ruby-shell-backtick-execution","reason":"The instruction places a user-selected SYMBOL directly into a shell command template without quoting. A substituted value containing shell syntax could execute unintended commands.","verdict":"confirmed","severity":"medium","confidence":0.91},{"id":"external_commands:SKILL.md:87:ruby-shell-backtick-execution","reason":"This line specifies a Markdown output filename and report format. It does not invoke an external command, although filename validation is still advisable.","verdict":"false_positive","confidence":0.97},{"id":"external_commands:SKILL.md:91:ruby-shell-backtick-execution","reason":"The fallback shows a direct shell template with cmd and SYMBOL placeholders and no quoting or allowlist. Unsafe substituted values could alter arguments or execute shell syntax.","verdict":"confirmed","severity":"medium","confidence":0.88},{"id":"external_commands:SKILL.md:92:ruby-shell-backtick-execution","reason":"The backticks document fixed Longbridge flags and subcommands for the intended fallback. They do not use shell substitution or construct a complete dynamic command on this line.","verdict":"false_positive","confidence":0.95},{"id":"external_commands:SKILL.md:93:ruby-shell-backtick-execution","reason":"Backticks format two example Hong Kong ticker strings. No command is executed.","verdict":"false_positive","confidence":0.99},{"id":"external_commands:SKILL.md:94:ruby-shell-backtick-execution","reason":"The inline text describes a configuration command the user may have already run. It does not direct automatic execution, and the network trust concern is adjudicated separately.","verdict":"false_positive","confidence":0.96},{"id":"external_commands:SKILL.md:95:ruby-shell-backtick-execution","reason":"The example embeds RAW_DIR inside Python source passed through a shell command. An untrusted path containing quotes or shell expansions could modify the Python expression or the surrounding command.","verdict":"confirmed","severity":"medium","confidence":0.9},{"id":"external_commands:SKILL.md:105:ruby-shell-backtick-execution","reason":"The backticks are part of a Markdown link naming a sibling skill. No external command is executed.","verdict":"false_positive","confidence":1},{"id":"external_commands:SKILL.md:106:ruby-shell-backtick-execution","reason":"This is a Markdown link to the fundamentals sibling skill. The code formatting has no execution semantics.","verdict":"false_positive","confidence":1},{"id":"external_commands:SKILL.md:107:ruby-shell-backtick-execution","reason":"This is a Markdown link to the research sibling skill. It does not execute a command.","verdict":"false_positive","confidence":1},{"id":"external_commands:SKILL.md:108:ruby-shell-backtick-execution","reason":"This is a formatted Markdown link to another skill. It has no shell or Ruby execution behavior.","verdict":"false_positive","confidence":1},{"id":"external_commands:SKILL.md:109:ruby-shell-backtick-execution","reason":"The match is the formatted label of a sibling-skill link. It is not executable code.","verdict":"false_positive","confidence":1},{"id":"external_commands:SKILL.md:110:ruby-shell-backtick-execution","reason":"The backticks format the market-data skill name inside a Markdown link. No command execution occurs.","verdict":"false_positive","confidence":1},{"id":"network:SKILL.md:94:hardcoded-url","reason":"The fallback introduces a remote MCP endpoint and instructs the agent to discover and use its tools. This expands the trust boundary and may transmit user queries to an external service.","verdict":"confirmed","severity":"low","confidence":0.92},{"id":"network:SKILL.md:97:hardcoded-url","reason":"This is a visible HTTPS documentation link for the Longbridge CLI. The line does not fetch the URL or transmit data.","verdict":"false_positive","confidence":0.98},{"id":"filesystem:SKILL.md:105:path-traversal-sequence","reason":"The ../ sequence is a relative Markdown link to a sibling skill directory. It is not applied to user input or used by a filesystem API.","verdict":"false_positive","confidence":1},{"id":"filesystem:SKILL.md:106:path-traversal-sequence","reason":"The relative path is a static Markdown navigation link. It does not perform a filesystem read or write.","verdict":"false_positive","confidence":1},{"id":"filesystem:SKILL.md:107:path-traversal-sequence","reason":"This static ../ path links to the sibling research skill in documentation. It is not a traversal operation.","verdict":"false_positive","confidence":1},{"id":"filesystem:SKILL.md:108:path-traversal-sequence","reason":"This is a fixed Markdown link to a sibling directory, with no untrusted path construction or filesystem access.","verdict":"false_positive","confidence":1},{"id":"filesystem:SKILL.md:109:path-traversal-sequence","reason":"The ../ sequence is documentation navigation to a sibling skill. It does not escape an application-controlled filesystem root.","verdict":"false_positive","confidence":1},{"id":"filesystem:SKILL.md:110:path-traversal-sequence","reason":"The static relative link points to the market-data sibling skill. It is not used in a file operation and cannot traverse based on user input.","verdict":"false_positive","confidence":1}],"semantic_findings":[{"title":"Unvalidated Symbol Controls Output Path","severity":"high","locations":[{"file":"scripts/collect.py","line_end":213,"line_start":203}],"confidence":0.97,"description":"The command-line symbol is inserted into a temporary directory name after only replacing periods. Slash and parent-directory segments can redirect fixed JSON and error files outside the intended directory.","confidence_reasoning":"The data flow from sys.argv to the Path expression is direct, and no allowlist or path containment check is present."},{"title":"Failed Refresh Can Reuse Stale Financial Data","severity":"high","locations":[{"file":"scripts/collect.py","line_end":56,"line_start":50},{"file":"scripts/collect.py","line_end":189,"line_start":176},{"file":"scripts/collect.py","line_end":213,"line_start":212}],"confidence":0.98,"description":"A failed fetch writes an error file but leaves any older JSON file intact. The reporting path prefers JSON over errors, so a new analysis can silently use stale results.","confidence_reasoning":"The output directory is stable per symbol, failure does not remove prior JSON, and section reads JSON before checking the current error file."}],"subject_marketplace_commit_sha":"656be3040aef5c047555a908cd5c695d22a4a548","subject_content_hash":"c07f8a43364014dab445d1e3d2b455974a268c5ac1376ca6e9c0960a780428cf","subject_tree_hash":"a62d2ac981898e1c385ce8f2f33217ba7f32c9381389acb40d9fc6e7ea1b0c2c","subject_plugin_path":"skills/longbridge/longbridge-earnings","audit_payload_hash":"fd489d5c1699dbf70e8da349c1548e11","confirmed_risk_level":"high","scanner_version":"3.0.0","policy_version":"skillstore-security-audit-policy-v1","subject":{"marketplaceCommitSha":"656be3040aef5c047555a908cd5c695d22a4a548","contentHash":"c07f8a43364014dab445d1e3d2b455974a268c5ac1376ca6e9c0960a780428cf","treeHash":"a62d2ac981898e1c385ce8f2f33217ba7f32c9381389acb40d9fc6e7ea1b0c2c","pluginPath":"skills/longbridge/longbridge-earnings","auditPayloadHash":"fd489d5c1699dbf70e8da349c1548e11"},"scannerVersion":"3.0.0","policyVersion":"skillstore-security-audit-policy-v1"},"auditTranslation":null,"localization":{"requestedLocale":"en","contentLocale":"en","availableLocales":["en"],"fallbackToEnglish":false},"attestation":{"availability":"issued","url":"/api/skills/longbridge-longbridge-earnings/audits/8/attestation","status":"active"},"trust":{"publicState":"public","auditState":"complete","auditCurrentness":null,"confirmedRiskLevel":"high","confirmedFindingCount":2,"capabilityReviewCount":7,"needsReviewCount":0,"falsePositiveCount":0,"agentAutoInstallPolicy":"confirmation_required","manualInstallPolicy":"allowed","artifactSignatureState":"available","attestationState":"active","verificationState":"not_verified"},"isLatest":true}}