google-workspace — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited google-workspace (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Gmail, Calendar, Drive, Contacts, Sheets, and Docs — powered by gws (Google's official Rust CLI). The skill provides a backward-compatible Python wrapper that handles OAuth token refresh and delegates to gws.
google_api.py → gws_bridge.py → gws CLI
(argparse compat) (token refresh) (Google APIs)setup.py handles OAuth2 (headless-compatible, works on CLI/Telegram/Discord)gws_bridge.py refreshes the Zorro token and injects it into gws via GOOGLE_WORKSPACE_CLI_TOKENgoogle_api.py provides the same CLI interface as v1 but delegates to gwsreferences/gmail-search-syntax.md — Gmail search operators (is:unread, from:, newer_than:, etc.)scripts/setup.py — OAuth2 setup (run once to authorize)scripts/gws_bridge.py — Token refresh bridge to gws CLIscripts/google_api.py — Backward-compatible API wrapper (delegates to gws)Install gws:
cargo install google-workspace-cli
# or via npm (recommended, downloads prebuilt binary):
npm install -g @googleworkspace/cli
# or via Homebrew:
brew install googleworkspace-cliVerify: gws --version
The setup is fully non-interactive — you drive it step by step so it works on CLI, Telegram, Discord, or any platform.
Define a shorthand first:
ZORRO_HOME="${ZORRO_HOME:-$HOME/.zorro}"
GWORKSPACE_SKILL_DIR="$ZORRO_HOME/skills/productivity/google-workspace"
PYTHON_BIN="${ZORRO_PYTHON:-python3}"
if [ -x "$ZORRO_HOME/zorro-agent/venv/bin/python" ]; then
PYTHON_BIN="$ZORRO_HOME/zorro-agent/venv/bin/python"
fi
GSETUP="$PYTHON_BIN $GWORKSPACE_SKILL_DIR/scripts/setup.py"$GSETUP --checkIf it prints AUTHENTICATED, skip to Usage — setup is already done.
Question 1: "What Google services do you need? Just email, or also Calendar/Drive/Sheets/Docs?"
himalaya skill instead — simpler setup.Partial scopes: Users can authorize only a subset of services. The setup script accepts partial scopes and warns about missing ones.
Question 2: "Does your Google account use Advanced Protection?"
Tell the user:
1. Go to https://console.cloud.google.com/apis/credentials 2. Create a project (or use an existing one) 3. Enable the APIs you need (Gmail, Calendar, Drive, Sheets, Docs, People) 4. Credentials → Create Credentials → OAuth 2.0 Client ID → Desktop app 5. Download JSON and tell me the file path
$GSETUP --client-secret /path/to/client_secret.json$GSETUP --auth-urlSend the URL to the user. After authorizing, they paste back the redirect URL or code.
$GSETUP --auth-code "THE_URL_OR_CODE_THE_USER_PASTED"$GSETUP --checkShould print AUTHENTICATED. Token refreshes automatically from now on.
All commands go through the API script:
ZORRO_HOME="${ZORRO_HOME:-$HOME/.zorro}"
GWORKSPACE_SKILL_DIR="$ZORRO_HOME/skills/productivity/google-workspace"
PYTHON_BIN="${ZORRO_PYTHON:-python3}"
if [ -x "$ZORRO_HOME/zorro-agent/venv/bin/python" ]; then
PYTHON_BIN="$ZORRO_HOME/zorro-agent/venv/bin/python"
fi
GAPI="$PYTHON_BIN $GWORKSPACE_SKILL_DIR/scripts/google_api.py"$GAPI gmail search "is:unread" --max 10
$GAPI gmail get MESSAGE_ID
$GAPI gmail send --to [email protected] --subject "Hello" --body "Message text"
$GAPI gmail send --to [email protected] --subject "Report" --body "<h1>Q4</h1>" --html
$GAPI gmail reply MESSAGE_ID --body "Thanks, that works for me."
$GAPI gmail labels
$GAPI gmail modify MESSAGE_ID --add-labels LABEL_ID$GAPI calendar list
$GAPI calendar create --summary "Standup" --start 2026-03-01T10:00:00+01:00 --end 2026-03-01T10:30:00+01:00
$GAPI calendar create --summary "Review" --start ... --end ... --attendees "[email protected],[email protected]"
$GAPI calendar delete EVENT_ID$GAPI drive search "quarterly report" --max 10
$GAPI drive search "mimeType='application/pdf'" --raw-query --max 5$GAPI contacts list --max 20$GAPI sheets get SHEET_ID "Sheet1!A1:D10"
$GAPI sheets update SHEET_ID "Sheet1!A1:B2" --values '[["Name","Score"],["Alice","95"]]'
$GAPI sheets append SHEET_ID "Sheet1!A:C" --values '[["new","row","data"]]'$GAPI docs get DOC_IDFor operations not covered by the wrapper, use gws_bridge.py directly:
GBRIDGE="$PYTHON_BIN $GWORKSPACE_SKILL_DIR/scripts/gws_bridge.py"
$GBRIDGE calendar +agenda --today --format table
$GBRIDGE gmail +triage --labels --format json
$GBRIDGE drive +upload ./report.pdf
$GBRIDGE sheets +read --spreadsheet SHEET_ID --range "Sheet1!A1:D10"All commands return JSON via gws --format json. Key output shapes:
body.content for text extraction)Parse output with jq or read JSON directly.
setup.py --check.| Problem | Fix |
|---|---|
NOT_AUTHENTICATED | Run setup Steps 2-5 |
REFRESH_FAILED | Token revoked — redo Steps 3-5 |
gws: command not found | Install: npm install -g @googleworkspace/cli |
HttpError 403 | Missing scope — $GSETUP --revoke then redo Steps 3-5 |
HttpError 403: Access Not Configured | Enable API in Google Cloud Console |
| Advanced Protection blocks auth | Admin must allowlist the OAuth client ID |
$GSETUP --revoke~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.