Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 51Code Agent Skills

This repository is the source package for 15 skills maintained by 51Code and
This repository is the source package for 16 skills maintained by 51Code and
the bootstrap for our reviewed machine-global skill baseline.

The repository intentionally has no catalog, registry, generated lock, sync
Expand All @@ -9,14 +9,15 @@ package directly.

## Global baseline

The global baseline supports Codex and Claude Code and contains these 38 skills:
The global baseline supports Codex and Claude Code and contains these 39 skills:

- 51Code-owned: `code-review`, `gemini-files-api`, `harness-engineering`,
`hint-overlay-visual-verification`, `ios-xcodegen`,
`lifecycle-and-side-effects-correctness`, `local-model-serving`,
`mechanism-audit`,
`meeting-transcription`, `silent-pushes-setup`, `spec-creation-updating`,
`swift-testing`, `swiftui-view-refactor`, `xcode-build`, and `xcode-cloud`
`meeting-transcription`, `public-source-release-audit`,
`silent-pushes-setup`, `spec-creation-updating`, `swift-testing`,
`swiftui-view-refactor`, `xcode-build`, and `xcode-cloud`

- Third-party: `swift-concurrency` and the 22 `asc-*` App Store Connect CLI
skills from `rorkai/app-store-connect-cli-skills`
Expand All @@ -37,7 +38,7 @@ idempotent. The script uses `skills@1.5.14`, explicit Git tags or commits, and
explicit skill names. In this CLI, `#ref` selects a Git branch or tag; `@name`
selects a skill and must not be used as a version pin. Sources pinned to a raw
commit are checked out and verified before being passed to the manager as a
local source. Before reporting success, the script verifies all 38 entrypoints
local source. Before reporting success, the script verifies all 39 entrypoints
in the shared and Claude Code manager roots and bootstraps the copied
`gemini-files-api` dependencies in both roots. The Claude Code root honors
`CLAUDE_CONFIG_DIR` when it is set. The script also converts the pinned
Expand Down
1 change: 1 addition & 0 deletions bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ owned_skills=(
local-model-serving
mechanism-audit
meeting-transcription
public-source-release-audit
silent-pushes-setup
spec-creation-updating
swift-testing
Expand Down
79 changes: 79 additions & 0 deletions public-source-release-audit/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
name: public-source-release-audit
description: Check a Git repository's current candidate for high-confidence credential, private-key, and machine-home leaks, then perform a bounded public-release review. Use before publishing source or opening a public PR; do not use it to claim complete history or workflow-execution safety.
---

# Public-Source Release Audit

Use this skill to answer a narrow question honestly: does the current source
candidate contain a supported high-confidence leak, and have the separate
human and GitHub-native release checks been confirmed?

## Automated Current-Source Check

Run the repository's own verifier when it exists. Then run:

```bash
ruby <skill-directory>/scripts/check_current_source.rb <repository>
```

The checker reads exact Git-index blobs so an unstaged replacement cannot hide
the candidate. It also scans tracked and non-ignored untracked worktree files
for early feedback. It reports only paths and finding categories, never the
matched content.

The supported categories are deliberately small:

- private-key headers;
- GitHub, AWS, and OpenAI credential formats;
- explicit bearer credentials; and
- absolute macOS, Linux, and Windows user-home paths.

Stage all intended release changes before relying on the candidate result.
Ignored files and submodule contents are outside this check. The checker does
not inspect Git history.

## Semantic Review

Automation cannot decide whether prose, filenames, images, or other assets
contain customer information, internal links, personal data, or company-only
context. Inspect the complete tree before first publication and the exact diff
for later releases. Mark this check unconfirmed unless a reviewer actually
performed it.

## GitHub-Native Controls

For an existing public GitHub repository, use read-only GitHub commands to
confirm the live state rather than recreating GitHub policy logic locally:

```bash
gh repo view OWNER/REPO --json visibility,defaultBranchRef
gh api repos/OWNER/REPO --jq '{visibility,security_and_analysis}'
gh ruleset check --default --repo OWNER/REPO
gh ruleset list --repo OWNER/REPO --parents --limit 100
gh ruleset view RULESET-ID --repo OWNER/REPO
Comment thread
VladimirBrejcha marked this conversation as resolved.
Comment thread
VladimirBrejcha marked this conversation as resolved.
gh api 'repos/OWNER/REPO/actions/runners?per_page=100' \
--jq '{total_count,runners:[.runners[] | {name,status,busy}]}'
```

Inspect applicable rulesets when necessary to confirm the required hosted
check, update strictness, and bypass actors. If authorization cannot expose a
setting, report it as unconfirmed. Do not weaken or mutate settings unless the
user separately authorizes that action.

## Result

Report these fields separately:

- repository verifier: `passed`, `failed`, or `not available`;
- automated current-source check: `passed` or `failed`;
- semantic context review: `confirmed` or `unconfirmed`;
- GitHub-native controls: `confirmed`, `unconfirmed`, or `not applicable`;
- history review: normally `not performed`;
- bounded verdict: `ready` only when every check required for this release is
passed or confirmed.

Do not summarize the bounded verdict as “the repository is safe.” Full-history
investigation is a separate, exceptional workflow using established tooling.
Publishing, rewriting history, revoking credentials, and changing repository
settings remain separate actions requiring their own authorization.
157 changes: 157 additions & 0 deletions public-source-release-audit/scripts/check_current_source.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

require "open3"
require "set"

RULES = [
[
"machine-local home path",
%r{(?:\A|[\s"'`=:(,])/(?:Users|home)/[A-Za-z0-9._-]+(?:/|\b)|\b[A-Za-z]:[\\/]Users[\\/][^\\/\r\n]+(?:[\\/]|$)}
Comment thread
VladimirBrejcha marked this conversation as resolved.
Outdated
],
["AWS access key", /\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/],
Comment thread
VladimirBrejcha marked this conversation as resolved.
["bearer credential", /Authorization\s*:\s*Bearer\s+[A-Za-z0-9._~+\/=:-]{16,}/i],
Comment thread
VladimirBrejcha marked this conversation as resolved.
Outdated
[
"GitHub token",
/\b(?:gh[pousr]_[A-Za-z0-9]{20,}|github_pat_[A-Za-z0-9_]{20,})\b/
],
["OpenAI API key", /\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\b/],
[
"private key",
/-----BEGIN (?:[A-Z0-9][A-Z0-9 ]* )?PRIVATE KEY-----/
Comment thread
VladimirBrejcha marked this conversation as resolved.
Outdated
]
].freeze

INDEX_BLOB_MODES = %w[100644 100755 120000].freeze
GIT_ENVIRONMENT = {
Comment thread
VladimirBrejcha marked this conversation as resolved.
"GIT_ALTERNATE_OBJECT_DIRECTORIES" => nil,
"GIT_COMMON_DIR" => nil,
"GIT_DIR" => nil,
"GIT_INDEX_FILE" => nil,
"GIT_NO_REPLACE_OBJECTS" => "1",
"GIT_OBJECT_DIRECTORY" => nil,
"GIT_WORK_TREE" => nil
}.freeze

def usage(message = nil)
warn message if message
warn "Usage: check_current_source.rb [repository]"
exit 64
end

def git_capture(repo, *arguments)
Open3.capture3(GIT_ENVIRONMENT, "git", "-C", repo, *arguments)
Comment thread
VladimirBrejcha marked this conversation as resolved.
Outdated
end

def scan_source(content, relative_path, findings, sensitive_paths = nil)
source = content.b
Comment thread
VladimirBrejcha marked this conversation as resolved.
RULES.each do |label, pattern|
next unless pattern.match?(source)

findings.add([relative_path, label])
sensitive_paths&.add(relative_path)
end
end

def display_path(relative_path, sensitive_paths)
sensitive_paths.include?(relative_path) ? "<redacted path>" : relative_path.dump
end

usage("Too many arguments") if ARGV.length > 1
repo = File.expand_path(ARGV.first || ".")
Comment thread
VladimirBrejcha marked this conversation as resolved.
usage("Repository must be a directory") unless File.directory?(repo)

index_output, _index_error, index_status = git_capture(
repo,
"ls-files",
Comment thread
VladimirBrejcha marked this conversation as resolved.
"--stage",
"-z"
)
usage("Repository must be a Git worktree") unless index_status.success?

errors = Set.new
findings = Set.new
sensitive_paths = Set.new
blob_cache = {}
index_entries = index_output.split("\0").reject(&:empty?).filter_map do |record|
Comment thread
VladimirBrejcha marked this conversation as resolved.
Outdated
metadata, relative_path = record.split("\t", 2)
mode, object_id, stage = metadata&.split(" ", 3)
unless mode && object_id && stage && relative_path
errors.add([relative_path || "<unknown>", "unreadable Git index entry"])
next
end

if stage != "0"
errors.add([relative_path, "unresolved Git index entry"])
next
end

{ mode: mode, object_id: object_id, path: relative_path }
end

index_entries.each do |entry|
relative_path = entry.fetch(:path)
scan_source(relative_path, relative_path, findings, sensitive_paths)
next if entry.fetch(:mode) == "160000"

unless INDEX_BLOB_MODES.include?(entry.fetch(:mode))
errors.add([relative_path, "unsupported Git index mode"])
next
end

object_id = entry.fetch(:object_id)
content = blob_cache[object_id]
unless content
content, _blob_error, blob_status = git_capture(
repo,
"cat-file",
"blob",
object_id
Comment thread
VladimirBrejcha marked this conversation as resolved.
Outdated
Comment thread
VladimirBrejcha marked this conversation as resolved.
Outdated
Comment thread
VladimirBrejcha marked this conversation as resolved.
Outdated
)
unless blob_status.success?
errors.add([relative_path, "unable to read Git index blob"])
next
end
blob_cache[object_id] = content
Comment thread
VladimirBrejcha marked this conversation as resolved.
Outdated
end
scan_source(content, relative_path, findings)
end

worktree_output, _worktree_error, worktree_status = git_capture(
repo,
"ls-files",
"-co",
"--exclude-standard",
"-z"
)
usage("Unable to enumerate repository worktree source") unless worktree_status.success?

worktree_paths = worktree_output.split("\0").reject(&:empty?).uniq
worktree_paths.each do |relative_path|
absolute_path = File.join(repo, relative_path)
scan_source(relative_path, relative_path, findings, sensitive_paths)
begin
content = if File.symlink?(absolute_path)
File.readlink(absolute_path)
elsif File.file?(absolute_path)
Comment thread
VladimirBrejcha marked this conversation as resolved.
Outdated
File.binread(absolute_path)
Comment thread
VladimirBrejcha marked this conversation as resolved.
Outdated
end
scan_source(content, relative_path, findings) if content
rescue SystemCallError
errors.add([relative_path, "unable to read worktree source"])
end
end

unless errors.empty? && findings.empty?
warn "current public-source check failed:"
errors.to_a.sort.each do |relative_path, label|
warn "- #{display_path(relative_path, sensitive_paths)}: #{label}"
end
findings.to_a.sort.each do |relative_path, label|
warn "- #{display_path(relative_path, sensitive_paths)}: #{label}"
end
warn "Matched content is intentionally omitted." unless findings.empty?
exit 1
end

puts "current public-source check passed"
Loading