Token导航 LogoToken导航TokenDH.com
开发可写文件github未标认证来源可访问许可证需确认审计通过

rust-securityRust 安全

Agent Skill

用于辅助安全审计、权限检查、凭据风险、认证流程和常见漏洞排查。它适合让 Agent 梳理敏感配置、检查依赖风险、分析鉴权逻辑或生成安全复核清单。使用时不能把工具输出直接当最终结论,涉及密钥、令牌、用户数据或生产系统时,应先确认最小权限、脱敏方式和操作边界。

总安装

964

周安装

39

GitHub Stars

12

下载量

303
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:rust-security(Rust 安全)
来源仓库:https://github.com/claude-dev-suite/claude-dev-suite
仓库路径:skills/rust-security
安装命令:
npx skills add https://github.com/claude-dev-suite/claude-dev-suite --skill rust-security
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/claude-dev-suite/claude-dev-suite --skill rust-security

简介

Rust 安全工具用于辅助安全审计、权限检查、凭据风险和认证流程排查。

  • 适合让 Agent 梳理敏感配置、检查依赖风险或分析鉴权逻辑,生成安全复核清单。
  • 使用时不能将工具输出直接当作最终结论,涉及密钥、令牌或生产系统时应先确认最小权限和操作边界。
  • 通过 npx skills add 命令从指定 GitHub 仓库安装,需结合原始 README 核验具体用法。
  • 安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写操作。

SKILL.md

Rust Security - Quick Reference

When NOT to Use This Skill

  • General OWASP concepts - Use owasp or owasp-top-10 skill
  • Java security - Use java-security skill
  • Python security - Use python-security skill
  • Secrets management - Use secrets-management skill
Deep Knowledge: Use mcp__documentation__fetch_docs with technology: rust for Rust security documentation.

Rust's Built-in Security Advantages

Rust provides memory safety by default:

  • No null pointer dereferences (Option instead)
  • No buffer overflows (bounds checking)
  • No use-after-free (ownership system)
  • No data races (borrow checker)

However, Rust does NOT protect against:

  • Logic errors (authorization bugs)
  • SQL injection (string handling)
  • XSS (template handling)
  • Secrets exposure
  • Dependency vulnerabilities

Dependency Auditing

# cargo-audit - Check for known vulnerabilities
cargo install cargo-audit
cargo audit

# cargo-deny - Policy-based linting
cargo install cargo-deny
cargo deny check

# Check outdated dependencies
cargo install cargo-outdated
cargo outdated

# Snyk for Rust
snyk test

cargo-deny Configuration (deny.toml)

[advisories]
vulnerability = "deny"
unmaintained = "warn"
yanked = "deny"

[licenses]
unlicensed = "deny"
allow = ["MIT", "Apache-2.0", "BSD-3-Clause"]

[bans]
multiple-versions = "warn"
wildcards = "deny"

[sources]
unknown-registry = "deny"
unknown-git = "deny"

CI/CD Integration

# GitHub Actions
- name: Security audit
  run: |
    cargo install cargo-audit
    cargo audit

- name: Dependency policy check
  run: |
    cargo install cargo-deny
    cargo deny check

SQL Injection Prevention

SQLx - Safe (Compile-time Checked)

use sqlx::{PgPool, query_as};

// SAFE - Compile-time verified query
let user: Option<User> = sqlx::query_as!(
    User,
    "SELECT * FROM users WHERE email = $1",
    email
)
.fetch_optional(&pool)
.await?;

// SAFE - Runtime query with bind
let user: Option<User> = sqlx::query_as::<_, User>(
    "SELECT * FROM users WHERE email = $1"
)
.bind(&email)
.fetch_optional(&pool)
.await?;

Diesel - Safe (Type-safe ORM)

use diesel::prelude::*;

// SAFE - Type-safe query
let user = users::table
    .filter(users::email.eq(&email))
    .first::<User>(&mut conn)
    .optional()?;

// SAFE - Explicit parameter binding
diesel::sql_query("SELECT * FROM users WHERE email = $1")
    .bind::<Text, _>(&email)
    .load::<User>(&mut conn)?;

UNSAFE Patterns

// UNSAFE - String formatting
let query = format!("SELECT * FROM users WHERE email = '{}'", email);  // NEVER!

// UNSAFE - String concatenation
let query = "SELECT * FROM users WHERE email = '".to_owned() + &email + "'";  // NEVER!

XSS Prevention

Askama (Compile-time Templates - Auto-escaping)

use askama::Template;

#[derive(Template)]
#[template(path = "page.html")]
struct PageTemplate<'a> {
    user_input: &'a str,  // Auto-escaped in template
}
<!-- page.html - auto-escaped -->
<p>{{ user_input }}</p>

<!-- Explicit raw (use with caution) -->
<p>{{ user_input|safe }}</p>  <!-- Only if already sanitized -->

Tera (Runtime Templates)

use tera::{Tera, Context};

let tera = Tera::new("templates/**/*")?;
let mut ctx = Context::new();
ctx.insert("user_input", &user_input);  // Auto-escaped

let rendered = tera.render("page.html", &ctx)?;

Manual Sanitization with ammonia

use ammonia::clean;

// Sanitize HTML input
let safe_html = clean(&user_input);

// Custom policy
use ammonia::Builder;

let safe_html = Builder::default()
    .tags(hashset!["p", "b", "i", "a"])
    .url_schemes(hashset!["http", "https"])
    .link_rel(Some("noopener noreferrer"))
    .clean(&user_input)
    .to_string();

Authentication - JWT

jsonwebtoken

use jsonwebtoken::{encode, decode, Header, Algorithm, Validation, EncodingKey, DecodingKey};
use serde::{Serialize, Deserialize};
use chrono::{Utc, Duration};

#[derive(Debug, Serialize, Deserialize)]
struct Claims {
    sub: String,       // user_id
    email: String,
    exp: usize,        // expiration
    iat: usize,        // issued at
}

fn generate_token(user_id: &str, email: &str, secret: &[u8]) -> Result<String, Error> {
    let expiration = Utc::now()
        .checked_add_signed(Duration::hours(1))
        .expect("valid timestamp")
        .timestamp() as usize;

    let claims = Claims {
        sub: user_id.to_owned(),
        email: email.to_owned(),
        exp: expiration,
        iat: Utc::now().timestamp() as usize,
    };

    encode(
        &Header::new(Algorithm::HS256),
        &claims,
        &EncodingKey::from_secret(secret)
    )
}

fn validate_token(token: &str, secret: &[u8]) -> Result<Claims, Error> {
    let mut validation = Validation::new(Algorithm::HS256);
    validation.validate_exp = true;

    let token_data = decode::<Claims>(
        token,
        &DecodingKey::from_secret(secret),
        &validation
    )?;

    Ok(token_data.claims)
}

Password Hashing with argon2

use argon2::{
    password_hash::{
        rand_core::OsRng,
        PasswordHash, PasswordHasher, PasswordVerifier, SaltString
    },
    Argon2
};

fn hash_password(password: &str) -> Result<String, Error> {
    let salt = SaltString::generate(&mut OsRng);
    let argon2 = Argon2::default();

    Ok(argon2
        .hash_password(password.as_bytes(), &salt)?
        .to_string())
}

fn verify_password(password: &str, hash: &str) -> Result<bool, Error> {
    let parsed_hash = PasswordHash::new(hash)?;
    Ok(Argon2::default()
        .verify_password(password.as_bytes(), &parsed_hash)
        .is_ok())
}

Input Validation with validator

use validator::{Validate, ValidationError};
use regex::Regex;
use lazy_static::lazy_static;

lazy_static! {
    static ref NAME_REGEX: Regex = Regex::new(r"^[a-zA-Z\s\-']+$").unwrap();
}

#[derive(Debug, Validate, Deserialize)]
struct CreateUserRequest {
    #[validate(email, length(max = 255))]
    email: String,

    #[validate(length(min = 12, max = 128), custom = "validate_password_strength")]
    password: String,

    #[validate(length(min = 2, max = 100), regex = "NAME_REGEX")]
    name: String,
}

fn validate_password_strength(password: &str) -> Result<(), ValidationError> {
    let has_upper = password.chars().any(|c| c.is_uppercase());
    let has_lower = password.chars().any(|c| c.is_lowercase());
    let has_digit = password.chars().any(|c| c.is_numeric());
    let has_special = password.chars().any(|c| "@$!%*?&".contains(c));

    if has_upper && has_lower && has_digit && has_special {
        Ok(())
    } else {
        Err(ValidationError::new("password_strength"))
    }
}

// Axum handler
async fn create_user(
    Json(payload): Json<CreateUserRequest>
) -> Result<Json<User>, AppError> {
    payload.validate()?;
    // payload is validated
}

Secure File Upload (Axum)

use axum::{
    extract::Multipart,
    response::Json,
};
use tokio::fs::File;
use tokio::io::AsyncWriteExt;
use uuid::Uuid;

const MAX_FILE_SIZE: usize = 10 * 1024 * 1024; // 10 MB
const ALLOWED_TYPES: &[&str] = &["image/jpeg", "image/png", "application/pdf"];

async fn upload_file(mut multipart: Multipart) -> Result<Json<UploadResponse>, AppError> {
    while let Some(field) = multipart.next_field().await? {
        let content_type = field.content_type()
            .ok_or(AppError::BadRequest("Missing content type"))?;

        // Validate content type
        if !ALLOWED_TYPES.contains(&content_type) {
            return Err(AppError::BadRequest("File type not allowed"));
        }

        let data = field.bytes().await?;

        // Validate size
        if data.len() > MAX_FILE_SIZE {
            return Err(AppError::BadRequest("File too large"));
        }

        // Generate safe filename
        let ext = match content_type {
            "image/jpeg" => "jpg",
            "image/png" => "png",
            "application/pdf" => "pdf",
            _ => return Err(AppError::BadRequest("Unknown type")),
        };
        let safe_name = format!("{}.{}", Uuid::new_v4(), ext);

        // Save file
        let path = format!("uploads/{}", safe_name);
        let mut file = File::create(&path).await?;
        file.write_all(&data).await?;

        return Ok(Json(UploadResponse { filename: safe_name }));
    }

    Err(AppError::BadRequest("No file provided"))
}

CORS Configuration (Axum)

use tower_http::cors::{CorsLayer, Any};
use http::{HeaderValue, Method};

let cors = CorsLayer::new()
    .allow_origin("https://myapp.com".parse::<HeaderValue>().unwrap())
    .allow_methods([Method::GET, Method::POST, Method::PUT, Method::DELETE])
    .allow_headers([http::header::AUTHORIZATION, http::header::CONTENT_TYPE])
    .allow_credentials(true);

let app = Router::new()
    .route("/api/users", get(get_users))
    .layer(cors);

Security Headers Middleware

use axum::{
    middleware::{self, Next},
    response::Response,
    http::Request,
};

async fn security_headers<B>(request: Request<B>, next: Next<B>) -> Response {
    let mut response = next.run(request).await;
    let headers = response.headers_mut();

    headers.insert("X-Content-Type-Options", "nosniff".parse().unwrap());
    headers.insert("X-Frame-Options", "DENY".parse().unwrap());
    headers.insert("X-XSS-Protection", "0".parse().unwrap());
    headers.insert("Referrer-Policy", "strict-origin-when-cross-origin".parse().unwrap());
    headers.insert("Content-Security-Policy", "default-src 'self'".parse().unwrap());
    headers.insert(
        "Strict-Transport-Security",
        "max-age=31536000; includeSubDomains".parse().unwrap()
    );

    response
}

// Apply to router
let app = Router::new()
    .route("/", get(index))
    .layer(middleware::from_fn(security_headers));

Rate Limiting

use governor::{Quota, RateLimiter};
use nonzero_ext::nonzero;
use std::sync::Arc;

// Create rate limiter
let limiter = Arc::new(RateLimiter::direct(
    Quota::per_minute(nonzero!(10u32))
));

// Middleware
async fn rate_limit<B>(
    State(limiter): State<Arc<RateLimiter<...>>>,
    request: Request<B>,
    next: Next<B>
) -> Result<Response, StatusCode> {
    match limiter.check() {
        Ok(_) => Ok(next.run(request).await),
        Err(_) => Err(StatusCode::TOO_MANY_REQUESTS),
    }
}

Secrets Management

use std::env;

#[derive(Clone)]
struct Config {
    jwt_secret: String,
    database_url: String,
    api_key: String,
}

impl Config {
    fn from_env() -> Result<Self, ConfigError> {
        Ok(Config {
            jwt_secret: env::var("JWT_SECRET")
                .map_err(|_| ConfigError::Missing("JWT_SECRET"))?,
            database_url: env::var("DATABASE_URL")
                .map_err(|_| ConfigError::Missing("DATABASE_URL"))?,
            api_key: env::var("API_KEY")
                .map_err(|_| ConfigError::Missing("API_KEY"))?,
        })
    }
}

// NEVER hardcode secrets
// const JWT_SECRET: &str = "hardcoded-secret";  // NEVER!

Logging Security Events

use tracing::{info, warn};

fn log_login_attempt(username: &str, success: bool, ip: &str) {
    info!(
        user = username,
        success = success,
        ip = ip,
        "login attempt"
    );
}

fn log_access_denied(user_id: &str, resource: &str, ip: &str) {
    warn!(
        user_id = user_id,
        resource = resource,
        ip = ip,
        "access denied"
    );
}

// NEVER log sensitive data
// info!(password = password, "user data");  // NEVER!

Unsafe Code Guidelines

// Minimize unsafe blocks
// Document why unsafe is necessary
// Encapsulate unsafe in safe abstractions

/// SAFETY: buffer is guaranteed to be valid UTF-8
/// because it was created from a valid String
unsafe fn process_buffer(buffer: &[u8]) -> &str {
    std::str::from_utf8_unchecked(buffer)
}

// Prefer safe alternatives
let s = std::str::from_utf8(buffer)?;  // Safe version

Anti-Patterns

Anti-PatternWhy It's BadCorrect Approach
format! in SQL querySQL injectionUse query macros with bind
`safe` filter on user inputXSS vulnerability
Hardcoded secretsSecret exposureUse environment variables
Excessive unsafe blocksMemory safety bypassMinimize and document unsafe
Ignoring cargo audit warningsKnown vulnerabilitiesUpdate or replace dependencies
Weak JWT algorithmsToken forgeryUse HS256 minimum
unwrap() in handlersPanic in productionUse proper error handling

Quick Troubleshooting

IssueLikely CauseSolution
cargo audit finds RUSTSECVulnerable crateUpdate with cargo update
JWT validation failsWrong algorithm/keyCheck Algorithm enum and key
CORS errorOrigin not configuredAdd origin to CorsLayer
Password hash slowArgon2 params too highAdjust memory/iterations
SQLx compile errorQuery doesn't match schemaRun cargo sqlx prepare
Template not escapingUsing `safe` filter

Security Scanning Commands

# Vulnerability audit
cargo audit

# Policy check
cargo deny check

# Clippy security lints
cargo clippy -- -W clippy::all -W clippy::pedantic

# Check for secrets
gitleaks detect
trufflehog git file://.

# SAST with semgrep
semgrep --config=p/rust .

Related Skills

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

34.19%
按下载量换算104

Claude

29.61%
按下载量换算90

Cursor

21.88%
按下载量换算66

Gemini CLI

11.03%
按下载量换算33

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

可写文件

该 Skill 可能写入或修改本地文件,使用前需要确认目标目录和修改范围。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills