Build1 distinct publisher3 min readPublished
An Apify Actor read a manifest, queried OSV, and filed one triage issue, with no branch or merge rights anywhere in its schema. The run that mattered was the second one, which updated the issue instead of filing a duplicate.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
The interesting part of the design is where the ceiling sits. The tool allowlist is declared in the Actor's input schema under `resourceType: "mcpConnector"`, and Apify's MCP proxy enforces it by filtering `tools/list` and rejecting calls outside the declared set [3][6]. So the restriction is not a promise made by the Actor's own code. It is applied on the path between the Actor and GitHub.
That matters because the author is explicit that the code itself stays untrusted: any allowed tool can be misused [11]. The claim being made is narrower and more useful than "this Actor is safe". It is that credential exfiltration and unlimited GitHub access are no longer preconditions of running the workflow [11]. The effective permission is the intersection of the schema allowlist, the connector's own permissions, and the scope of the underlying GitHub token [7]. Three layers, and the tightest one wins.
The credential handling is the part I would copy. At runtime the Actor gets a connector ID, the proxy base URL, and its own run token, and never sees the GitHub PAT or OAuth token held in the connector [8]. Compare that with the alternative the author names: pass a GitHub token into code you did not want handling tokens, or hand-copy repository contents into Actor input and hand-carry results back [5]. The connector fires at two boundaries, reading `package.json` and then searching for and writing the issue [4].
The server URL is pinned with a wildcard, `https://api.githubcopilot.com/mcp*`, which covers a trailing slash on the official endpoint and will not accept a different hostname [3][9]. That is the config line doing the work. A hostname wildcard broad enough to match an attacker-controlled host would undo the rest of it.
Then there is `confirmWriteTarget`. Dry run is the default, and a write run has to supply the exact `owner/repo` string [10]. The author is careful to say this is not a substitute for GitHub authorization, since the connector still enforces the caller's real permissions [10]. It is a guard against a toggled checkbox posting into the wrong repository. Cheap, and it addresses the failure mode that actually happens.
On the results: 16 advisory rows against a fixture repo with three intentionally old npm packages, on 8 August 2026 [1][2]. That is roughly five advisories per package, which is what a deliberately stale fixture is for. Do not read it as a base rate for your own tree. The number that transfers is the issue count, not the advisory count: after three runs, including one on published build 1.2.1, the repository still held exactly one issue [2][12]. For that to hold on your repo, `search_issues` has to reliably find the prior issue under your labelling and title conventions, and your triage issue has to be the only plausible match. Idempotency here is a search query, and search queries drift.
Three tools is also a real cost. No branch, no file edit, no merge, no other GitHub tool at all [3]. The Actor cannot bump a version or open the fix PR. It produces a source-linked review queue and a human does the rest [4]. Whether that is a feature depends on whether you were going to review the bot's PRs anyway.
Ranked by verification strength, evidence, and original report placement.
On August 8, 2026, the author ran the Actor against a public fixture repository containing three intentionally old npm packages; the run returned 16 advisory rows and created issue #1.
A second run with the same input updated issue #1 rather than creating a new one, and the repository still had exactly one issue.
The Actor is built around one GitHub MCP connector that can call exactly three GitHub tools: get_file_contents to read a dependency manifest, search_issues to find its previous triage issue, and issue_write to create or update that issue. It cannot edit a file, create a branch, merge code, or call any other GitHub tool. The connector declaration pins mcpServers url to https://api.githubcopilot.com/mcp* with those three tools listed as required.
The Actor extracts exact dependency versions, calls a separate OSV Actor, and writes a source-linked review queue; the connector fires twice, first when reading package.json and again when searching for and writing the triage issue.
Without the connector, the author says he would have had to copy repository contents into Actor input and move results back to GitHub manually, or pass a GitHub token into code he did not want handling it.
An Actor opts into connectors with resourceType: "mcpConnector"; the schema acts as a runtime ceiling because Apify's MCP proxy filters tools/list and rejects calls outside the declared set.
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · September 1, 2026
Follow any of these and your For You feed starts watching them — no settings page required.
build
Claude Code's new default is a confession: the approval prompt was never a control1 distinct publisher
build
Every one of thirteen named 2025-26 incidents ran on a credential that still worked1 distinct publisher
build
Existence checks are dead: attackers now register the packages your AI invents1 distinct publisher
product
Mozilla's fake Python tool talked a coding agent into opening a reverse shell1 distinct publisher
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Code shown, results self-reported
The design side is unusually checkable for a blog post: the connector declaration, the tool precheck, the version regexes and the MCP session code are all on the page, so a reader can judge whether the permission ceiling is drawn where the author says it is. The empirical side is a single first-person log with no fixture repository link, no rejected-call transcript and no second party who ran it. Design you can inspect; outcomes you can only believe.
One author, one fixture, one build
Three runs by the person who wrote the Actor, against a repository built to be vulnerable, is the whole footprint. A published build 1.2.1 exists, which is more than most walkthroughs can show, but nothing in this reporting indicates a user, a customer repository, an install count or a second engineer.
Headline flatters a fixture
Sixteen advisories against three packages chosen for being old is arithmetic, not discovery, and the title spends that number as if it were a finding. Everything below the title pulls the other way: the author names the second run rather than the first as the result he cares about, declines to guess what a version range resolved to, and refuses to call his write guard an authorization control. Small overstatement, and it sits in the headline rather than in the claims.
Vendor showcasing its own plumbing
This is published on dev.to under Apify's organization account, and the thing being praised is Apify's connector schema, Apify's MCP proxy and an Actor distributed through Apify's Store. The one enforcement claim a reader most needs verified — that the proxy rejects undeclared tool calls — is exactly the claim the publisher has an interest in. Working code and candid limits temper that, but they do not remove it.
Internally consistent, externally unchecked
The account holds together — dates, build number, tool names, guard behaviour and the parser's deliberate gaps all line up, and the author volunteers what he did not solve. What is missing is anyone outside Apify. Until a second party runs the Actor or a refused tool call is shown, the layered-permission argument is credible engineering description rather than established fact.