Google Services Secure
🔒 Security First
This skill implements enterprise-grade security protections for Google Workspace APIs:
- ✅ Credential Isolation - OAuth tokens and secrets never stored in config files
- ✅ Input Validation - All emails, file IDs, and parameters sanitized
- ✅ Audit Logging - Complete action trail with timestamps
- ✅ Rate Limiting - Prevents abuse and DoS
- ✅ Granular Permissions - Read-only mode by default
- ✅ Sandbox Support - Isolated execution environment
- ✅ OAuth 2.0 Flow - Secure authorization flow
- ✅ HTTPS Only - Enforces encrypted connections
- ✅ Confirmation Required - Dangerous operations need explicit approval
⚠️ Before Using
CRITICAL SECURITY REQUIREMENTS:
- Environment Variables MUST be Set:
# NEVER store these in openclaw.json or any config file
export GOOGLE_API_KEY="your-api-key"
export GOOGLE_CLIENT_ID="your-client-id"
export GOOGLE_CLIENT_SECRET="your-client-secret"
export GOOGLE_REDIRECT_URI="http://localhost:8080/callback"
- First-Time Setup Required:
cd /data/.openclaw/workspace/skills/google-services-secure
./scripts/validate-setup.sh
- OAuth 2.0 Flow:
# Generate OAuth URL and authenticate
./scripts/auth-google.sh
Quick Start
1. Configure Environment Variables
# Add to ~/.bashrc or /etc/environment
export GOOGLE_API_KEY="your-api-key"
export GOOGLE_CLIENT_ID="your-client-id.apps.googleusercontent.com"
export GOOGLE_CLIENT_SECRET="your-client-secret"
export GOOGLE_REDIRECT_URI="http://localhost:8080/callback"
# Reload shell
source ~/.bashrc
2. Validate Setup
cd /data/.openclaw/workspace/skills/google-services-secure
./scripts/validate-setup.sh
This will:
- Verify environment variables are set
- Validate Google API key format
- Test OAuth credentials
- Create audit log directory
- Report any security issues
3. Authenticate via OAuth 2.0
cd /data/.openclaw/workspace/skills/google-services-secure
./scripts/auth-google.sh
This will:
- Generate OAuth 2.0 authorization URL
- Open browser for user consent
- Capture authorization code
- Exchange code for access token
- Store tokens securely in memory
4. List Gmail Messages (Read-Only)
curl -s "https://gmail.googleapis.com/gmail/v1/users/me/messages?maxResults=10" \
-H "Authorization: Bearer $ACCESS_TOKEN"
-H "Content-Type: application/json"
Security Architecture
Credential Management
❌ NEVER do this:
{
"env": {
"GOOGLE_API_KEY": "AIza...", // ❌ INSECURE
"GOOGLE_CLIENT_ID": "...apps.googleusercontent.com", // ❌ INSECURE
"GOOGLE_CLIENT_SECRET": "..." // ❌ CRITICAL SECURITY ISSUE
}
}
✅ CORRECT approach:
# Set at system level, never in files
export GOOGLE_API_KEY="your-api-key"
export GOOGLE_CLIENT_ID="your-client-id.apps.googleusercontent.com"
export GOOGLE_CLIENT_SECRET="your-client-secret"
OAuth 2.0 Authorization Flow
Step 1: Generate Authorization URL
https://accounts.google.com/o/oauth2/v2/auth?client_id=$GOOGLE_CLIENT_ID \
&redirect_uri=$GOOGLE_REDIRECT_URI \
&response_type=code \
&scope=https://www.googleapis.com/auth/gmail.readonly,https://www.googleapis.com/auth/drive.readonly
Step 2: Exchange Code for Token
curl -X POST https://oauth2.googleapis.com/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=$GOOGLE_CLIENT_ID" \
-d "client_secret=$GOOGLE_CLIENT_SECRET" \
-d "code=$AUTHORIZATION_CODE" \
-d "redirect_uri=$GOOGLE_REDIRECT_URI" \
-d "grant_type=authorization_code"
Permissions System
The skill operates in three permission modes:
| Mode | Read | Write | Delete | Share | Risk Level |
|---|
readonly | ✅ | ❌ | ❌ | ❌ | 🟢 LOW |
restricted | ✅ | ✅* | ❌ | ❌ | 🟡 MEDIUM |
full | ✅ | ✅ | ✅* | ✅* | 🔴 HIGH |
- Requires explicit confirmation for each operation
Default mode: readonly
To change mode:
export GOOGLE_PERMISSION_MODE="readonly" # Recommended for production
Audit Logging
All actions are logged to:
/data/.openclaw/logs/google-services-audit.log
Log format:
{
"timestamp": "2024-04-04T00:30:45.123Z",
"user": "nelson",
"service": "gmail",
"action": "LIST_MESSAGES",
"status": "success",
"messageCount": 10,
"durationMs": 234,
"permissionMode": "readonly"
}
Rate Limiting
Default limits (configurable):
| Service | Limit | Window |
|---|
| Gmail API | 100 | per minute |
| Drive API | 500 | per minute |
| Calendar API | 100 | per minute |
| Sheets API | 100 | per minute |
| Contacts API | 50 | per minute |
Customize limits:
export GOOGLE_RATE_LIMIT_GMAIL="100/minute"
export GOOGLE_RATE_LIMIT_DRIVE="500/minute"
Available Services
📧 Gmail (gmail.googleapis.com)
1. List Messages
curl -s "https://gmail.googleapis.com/gmail/v1/users/me/messages?maxResults=10" \
-H "Authorization: Bearer $ACCESS_TOKEN"
2. Get Message
curl -s "https://gmail.googleapis.com/gmail/v1/users/me/messages/$MESSAGE_ID" \
-H "Authorization: Bearer $ACCESS_TOKEN"
3. Send Email (Requires Permission)
⚠️ Confirmation required before sending
curl -X POST "https://gmail.googleapis.com/gmail/v1/users/me/messages/send" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"raw": "From: me@example.com\r\nTo: recipient@example.com\r\nSubject: Test\r\n\r\nTest message body"
}'
💾 Google Drive (drive.googleapis.com)
1. List Files
curl -s "https://www.googleapis.com/drive/v3/files?pageSize=10" \
-H "Authorization: Bearer $ACCESS_TOKEN"
2. Upload File (Requires Permission)
⚠️ Confirmation required before uploading
curl -X POST "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-F "metadata={\"name\":\"test.txt\"};type=application/json; charset=UTF-8" \
-F "file=@test.txt"
3. Download File
curl -s "https://www.googleapis.com/drive/v3/files/$FILE_ID?alt=media" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-O downloaded_file.txt
📅 Google Calendar (calendar.googleapis.com)
1. List Events
curl -s "https://www.googleapis.com/calendar/v3/calendars/primary/events?maxResults=10" \
-H "Authorization: Bearer $ACCESS_TOKEN"
2. Create Event (Requires Permission)
⚠️ Confirmation required before creating
curl -X POST "https://www.googleapis.com/calendar/v3/calendars/primary/events" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"summary": "Meeting",
"start": {"dateTime": "2024-04-04T10:00:00Z"},
"end": {"dateTime": "2024-04-04T11:00:00Z"}
}'
📊 Google Sheets (sheets.googleapis.com)
1. List Spreadsheets
curl -s "https://sheets.googleapis.com/v4/spreadsheets" \
-H "Authorization: Bearer $ACCESS_TOKEN"
2. Read Sheet Values
curl -s "https://sheets.googleapis.com/v4/spreadsheets/$SPREADSHEET_ID/values/Sheet1!A1:B10" \
-H "Authorization: Bearer $ACCESS_TOKEN"
3. Update Sheet (Requires Permission)
⚠️ Confirmation required before updating
curl -X PUT "https://sheets.googleapis.com/v4/spreadsheets/$SPREADSHEET_ID/values/Sheet1!A1:B10" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"values": [["New Value"]]
}'
📝 Google Docs (docs.googleapis.com)
1. List Documents
curl -s "https://www.googleapis.com/drive/v3/files?q=mimeType%3D'application/vnd.google-apps.document'" \
-H "Authorization: Bearer $ACCESS_TOKEN"
2. Get Document Content
curl -s "https://www.googleapis.com/drive/v3/files/$DOC_ID/export?mimeType=text/plain" \
-H "Authorization: Bearer $ACCESS_TOKEN"
👥 Google Contacts (people.googleapis.com)
1. List Connections
curl -s "https://people.googleapis.com/v1/people/me/connections?personFields=names,emailAddresses" \
-H "Authorization: Bearer $ACCESS_TOKEN"
2. Create Contact (Requires Permission)
⚠️ Confirmation required before creating
curl -X POST "https://people.googleapis.com/v1/people:createContact" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"emailAddresses": [{"value": "new@example.com"}],
"names": [{"givenName": "John", "familyName": "Doe"}]
}'
Input Validation
Email Validation
function validateEmail(email) {
// Must be valid email format
if (!email.match(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/)) {
throw new Error('Invalid email format');
}
// No dangerous characters
if (email.match(/<script|javascript:|onerror|onload/i)) {
throw new Error('Email contains dangerous patterns');
}
return email;
}
File Path Validation
function validateFilePath(path) {
// Prevent directory traversal
if (path.includes('..') || path.includes('~')) {
throw new Error('Invalid file path');
}
// Validate file extension
const allowedExtensions = ['.txt', '.pdf', '.doc', '.docx', '.xls', '.xlsx'];
const extension = path.slice(-5);
if (!allowedExtensions.includes(extension)) {
throw new Error('File type not allowed');
}
return path;
}
Data Sanitization
function sanitizeData(data) {
const sensitive = ['password', 'apiKey', 'secret', 'token', 'credential'];
const sanitized = JSON.parse(JSON.stringify(data));
function clean(obj) {
for (const key in obj) {
if (sensitive.some(s => key.toLowerCase().includes(s))) {
obj[key] = '***REDACTED***';
} else if (typeof obj[key] === 'object') {
clean(obj[key]);
} else if (typeof obj[key] === 'string') {
// Remove potential HTML/Script tags
obj[key] = obj[key].replace(/<[^>]*>/g, '');
}
}
}
clean(sanitized);
return sanitized;
}
Coding Use Cases
Use Case 1: Email Automation
#!/bin/bash
# Send automated email notifications
EMAIL_SUBJECT="Daily Report"
RECIPIENT="manager@example.com"
MESSAGE_BODY="Daily report attached."
curl -X POST "https://gmail.googleapis.com/gmail/v1/users/me/messages/send" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"raw\": \"From: me@example.com\\r\\nTo: $RECIPIENT\\r\\nSubject: $EMAIL_SUBJECT\\r\\n\\r\\n$MESSAGE_BODY\"
}"
Use Case 2: File Backup
#!/bin/bash
# Backup files from Drive to local storage
curl -s "https://www.googleapis.com/drive/v3/files?pageSize=100" \
-H "Authorization: Bearer $ACCESS_TOKEN" | \
jq -r '.files[] | "\(.id) \t \(.name)"' | \
while read id name; do
curl -s "https://www.googleapis.com/drive/v3/files/$id?alt=media" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-O "backups/$name"
done
Use Case 3: Calendar Scheduling
#!/bin/bash
# Schedule automated calendar events
EVENT_SUMMARY="Weekly Meeting"
START_TIME=$(date -u +"%Y-%m-%dT%H:%M:00Z")
END_TIME=$(date -u -d +1hour +"%Y-%m-%dT%H:%M:00Z")
curl -X POST "https://www.googleapis.com/calendar/v3/calendars/primary/events" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"summary\": \"$EVENT_SUMMARY\",
\"start\": {\"dateTime\": \"$START_TIME\"},
\"end\": {\"dateTime\": \"$END_TIME\"}
}"
Security Best Practices
✅ DO
# Set environment variables at system level
export GOOGLE_API_KEY="your-api-key"
export GOOGLE_CLIENT_ID="your-client-id.apps.googleusercontent.com"
export GOOGLE_CLIENT_SECRET="your-client-secret"
# Use readonly mode in production
export GOOGLE_PERMISSION_MODE="readonly"
# Review audit logs regularly
tail -100 /data/.openclaw/logs/google-services-audit.log
# Validate setup before use
./scripts/validate-setup.sh
❌ DON'T
# NEVER store credentials in config files
{
"env": {
"GOOGLE_CLIENT_SECRET": "..." # ❌ CRITICAL SECURITY ISSUE
}
}
# NEVER use HTTP (unencrypted)
export GOOGLE_API_KEY="http://..." # ❌ INSECURE
# NEVER share access tokens
echo "$ACCESS_TOKEN" # ❌ LEAKS CREDENTIALS
Troubleshooting
Error: Invalid Credentials
Error: Invalid Credentials
Solution:
- Verify API key format
- Check client ID and secret
- Regenerate credentials in Google Cloud Console
Error: Invalid Grant
Error: Invalid grant
Solution:
- Verify redirect URI matches
- Check OAuth scopes
- Ensure authorization flow is correct
Error: Rate Limit Exceeded
Error: User Rate Limit Exceeded
Solution:
- Wait for quota to reset
- Reduce request frequency
- Upgrade Google Cloud quota
Error: Permission Denied
Error: 403 Forbidden
Solution:
- Verify OAuth scopes
- Check permission mode
- Re-authenticate if token expired
Security Checklist
Before using this skill in production, verify:
OpenClaw Integration
Recommended Configuration
{
"agents": {
"google-services": {
"id": "google-services",
"name": "Google Services (Secure)",
"skills": ["google-services-secure"],
"sandbox": "require",
"tools": {
"allowlist": ["curl", "read", "write"],
"denylist": ["exec", "eval", "shell"]
},
"maxConcurrent": 1
}
}
}
Enable Skill
# Add skill to main agent
openclaw agent add-skill main google-services-secure
# Or create dedicated agent
openclaw agent create google-services \
--skills google-services-secure \
--sandbox require \
--max-concurrent 1
References
Version History
- 1.0.0 (2024-04-04)
- Initial secure release
- OAuth 2.0 authorization flow
- Credential isolation (environment variables only)
- Input validation (email, file paths, sanitization)
- Audit logging with complete action trail
- Rate limiting to prevent abuse
- Granular permissions (readonly, restricted, full)
- Multi-service support (Gmail, Drive, Calendar, Sheets, Contacts)
- Confirmation required for dangerous operations
- HTTPS enforcement
- Setup validation scripts
License
MIT License - See LICENSE.md for details
Contributing
Security is top priority. All contributions must:
- Maintain security guarantees
- Include audit logging
- Pass validation checks
- Update documentation
- Add tests for security features
Support
⚠️ IMPORTANT: This skill prioritizes security over convenience. Read-only operations work immediately. Dangerous operations require explicit confirmation and appropriate permission levels.
Note: This skill uses OAuth 2.0 flow for secure authorization. Never share your access tokens or store them in files.