Shields.io

repository·master·Indexed 12 days ago

https://github.com/badges/shields

A service for providing concise, consistent, and legible badges in SVG and raster formats. Includes the badge-maker library and CLI for programmatically generating badges with customizable labels, messages, colors, and styles such as 'plastic', 'flat', 'flat-square', 'for-the-badge', and 'social'.

Tokens
28.6K
Snippets
87
Records
122
Agent score
98%

What's inside Shields.io

  1. Understand the Shields codebase architecture

    master

    The Shields codebase is organized into several distinct functional areas:

    • badge-maker: The badge renderer, available as an npm package.
    • frontend: The user-facing web interface.
    • core/base-service: The foundational service classes (approx. 8% of the code) that define how services behave.
    • core/server: The server implementation based on the Scoutcamp framework.
    • core/token-pooling: Utilities for managing tokens and persistence to prevent rate limiting (e.g., from GitHub).
    • services/: The actual service implementations (approx. 80% of the code). Each service resides in its own folder.
    • services/*.js (root of services): Common helper functions shared across services (approx. 7% of the code).
  2. Security update for Dynamic JSON/TOML/YAML badges

    master

    Shields.io has migrated its dynamic badge JSONPath querying from dchester/jsonpath to JSONPath-Plus to mitigate a remote code execution (RCE) vulnerability. This change involves using the eval: false option in JSONPath-Plus to disable script expressions, which is a critical security improvement for both the hosted service and self-hosted instances.

    Impact on users:

    • Backwards Compatibility: Some JSONPath queries that rely on evaluating JavaScript expressions are no longer supported.
    • Query Syntax: Queries like $..keywords[(@.length-1)] (which use JS logic) will fail. You should use standard JSONPath syntax instead, such as $..keywords[-1:] for selecting the last element of an array.
  3. Understand the GitHub OAuth App permissions and data usage

    master

    Users can optionally authorize the Shields.io GitHub OAuth app to increase rate limits for accessing the GitHub API.

    Data Collected:

    • GitHub token: Used solely to increase the rate limit for GitHub API access. It has read-only access to public data and cannot access private data or perform actions on your behalf.
    • Timestamp: Stored for internal record-keeping of when authorization occurred.

    Shields.io does not store usernames, email addresses, or any other personally identifiable information (PII).

  4. Handle query parameter conflicts in redirectors

    master

    By default, query parameters generated via transformQueryParams take precedence over parameters provided by the user in the URL string. If you want user-provided query parameters to win in a conflict, set overrideTransformedQueryParams: true.

    Example: If a user requests /old/service/token/abc123/foo?token=xyz789, setting overrideTransformedQueryParams: true ensures the resulting URL uses token=xyz789 instead of the path-extracted abc123.

    import { redirector } from '../index.js'
    
    export default redirector({
      category: 'build',
      route: {
        base: 'old/service',
        pattern: 'token/:token/:param',
      },
      transformPath: ({ param }) => `/new/service/${param}`,
      transformQueryParams: ({ token }) => ({ token }),
      overrideTransformedQueryParams: true,
      dateAdded: new Date('2025-04-04'),
    })
  5. Design guidelines for creating Shields badges

    master

    When creating or designing badges for use with Shields.io, follow these core principles to ensure quality and usability:

    • Legibility: Metadata must be as easy to read as body copy in a README, regardless of resolution.
    • Semantics: The purpose of the information must be self-evident.
    • Non-promotional: Avoid using the badge key to advertise a service. Instead, use the key to provide context for the value. If a service needs promotion, use the badge's hyperlink capability.
    • Conciseness: Follow the pattern of one descriptive word on the left (the key) and one piece of data on the right (the value).
    • Hyperlinking: For badges using the social style, use hyperlinks to direct users to third-party websites for more information.
  6. Understand authentication patterns for shields.io badges

    master

    shields.io supports two primary patterns for interacting with APIs that require authentication:

    1. Service-level tokens: A single token is stored at the server level to fetch public data or bypass rate limits for all users. This is typically used for global metrics.
    2. User-provided tokens: Users provide their own token directly in the badge URL as a query parameter.

    Security Constraint for User Tokens: If you are using a user-provided token, it must be a token that is safe to expose in a public README (e.g., a token that only provides access to public metrics). If a service requires a token that grants access to sensitive data or write permissions, shields.io cannot provide an integration for it because the token would be publicly visible in the badge URL.

  7. Configure authorized origins for service credentials

    master

    If you provide credentials for a service (like GitHub or DockerHub) on a self-hosted Shields instance, you must explicitly authorize the specific upstream hosts to which those credentials are allowed to be sent. This prevents credentials from being leaked to unauthorized servers.

    Behavior for unauthorized origins:

    • If credentials are required for the target service: Shields will render an error badge.
    • If credentials are optional for the target service: Shields will attempt the request but will not send the credentials.

    Configuration Rules:

    • Environment Variables: Separate multiple origins with a space.
    • Default State: If no origins are defined, the list defaults to empty (no origins are authorized).
    • Security Best Practice: Always use https origins with valid SSL to prevent credential exposure via DNS-based attacks. Use tokens following the Principle of Least Privilege (PoLP).
  8. Visual and aesthetic specifications for badges

    master

    Shields badges follow specific aesthetic rules to ensure consistency and readability:

    • Typography: Uses the Open Sans font face for high legibility at small sizes.
    • Sizing: Badges should never have a fixed width; they scale based on content.
    • Color & Contrast:
      • Focus on high contrast between text and background on both the key and value sides.
      • The key side generally uses a dark grey background for consistency.
      • The value side uses colors that convey meaning (e.g., green for success, red for failure).
      • Text Color: White is preferred, but black should be used if a light background is chosen to ensure legibility.
  9. How the Shields server processes a badge request

    master

    When an HTTPS request arrives, the server follows this lifecycle to generate a badge:

    1. Routing: The Scoutcamp framework matches the URL path against registered regexes from all services.
    2. Legacy Handling: A legacy handler extracts data from the regex match and queryParams and prepares to call sendBadge.
    3. Service Invocation: BaseService.invoke instantiates the specific service subclass and calls its handle() method.
    4. The handle() Method: The service subclass must implement handle() to return an object describing the badge (e.g., message, color, label) or throw a handled error class (e.g., NotFound, InvalidResponse, Inaccessible, InvalidParameter).
    5. Request Stages: A typical handle() implementation follows three stages:
      • fetch: Load and validate data from the upstream source.
      • transform: Convert the upstream response into properties suitable for a badge.
      • render: Determine the final message, color, and label.
    6. Coalescing: The coalesceBadge function merges query string overrides with service values and defaults.
    7. Rendering: The final object is passed to sendBadge, which renders the badge as SVG or raster and sends it over the connection.
  10. Service Badge File Structure

    master

    Service badge code is located in the /services directory. Each service typically has its own directory.

    • Single Badge Services: Code is stored in a file ending in .service.js (e.g., /services/example/example.service.js).
    • Service Families: For services with multiple related badges, each badge has its own file (e.g., /services/example/example-downloads.service.js and /services/example/example-version.service.js).
    • Tests: Files ending in .tester.js contain code to verify that badges are generated correctly using the shields server.
  11. Implement routeEnum for parameter validation

    master

    If a service defines a finite set of allowed values for a parameter, you can declare static routeEnum = [...].

    When this is defined, the first named parameter in the route pattern is automatically treated as the enum to validate against the routeEnum list.