Skip to content

Repository files navigation

Sliver Script

Sliver-script is a TypeScript/JavaScript client library for Sliver, it can be used to automate any operator interaction with Sliver. Sliver-script uses existing Sliver client configuration files and connects to servers using gRPC over Mutual-TLS. It also provides RxJS abstractions for easy interactions with real-time components.

This library targets modern Sliver protobuf/gRPC APIs and provides a strongly-typed TypeScript-first client.

Build Check Sliver End-to-End npm version License: GPL v3

The integrated wrapper provenance is pinned in integration.lock.json: standalone base 01f1029cc17898da681e52b64af4a708ff82c3d3, authoritative Sliver GUI source f0fa15af24365c9fdab1a2cdff769c88c1ad7cf6, and Sliver/protobuf source ca685f5eed64c3327c0e57504928cfd2d2e96bea. The package exposes explicit typed convenience methods and no method-name/request-object dispatcher. For compatibility it still exports the generated rpcpb namespace and the existing statically typed SliverClient.rpc getter; trusted applications must impose their own narrower capability boundary, as Sliver GUI does in its main-process adapter.

Install

Node v24 or later is required for this package, and it can be installed via npm:

npm install sliver-script

End-to-end tests

npm run test:e2e compiles the server from the pinned Sliver submodule, creates an isolated multiplayer profile with the server CLI, starts the native server, and runs the grouped TypeScript client tests against it. GitHub Actions runs the same path on Linux/amd64, Windows/amd64, and macOS/arm64. See e2e/README.md for the implemented groups and expansion plan.

Operator transport

Operator connections use direct mTLS. Configurations containing a WireGuard operator profile are rejected before credentials or channels are created. WireGuard listener and implant C2 APIs remain available.

Reproducible protobuf generation

Generated TypeScript under src/pb is locked to Sliver commit ca685f5eed64c3327c0e57504928cfd2d2e96bea, protoc 35.1, and ts-proto 2.12.1. The generator reads only the pinned sliver submodule; it never selects a neighboring checkout.

From a Git source checkout, install protoc 35.1 after npm ci, initialize the pinned submodule, and run:

git submodule update --init --recursive
npm run protobuf:check

npm run protobuf:generate rewrites the five checked-in protobuf modules only after the source commit, source tree, input hashes, descriptor hash, generator version, and generated byte hashes all match protobuf.lock.json.

That command is restorative, not an upgrade command. Advancing Sliver, protoc, or ts-proto requires a deliberate maintainer review that regenerates and updates every source, descriptor, and output hash in the lock together.

The npm tarball carries those generated TypeScript modules and their provenance lock, but deliberately excludes the Sliver submodule and therefore is not a self-contained protobuf regeneration checkout.

Before preparing a package, run npm run audit:all and npm run verify. Verification audits the exact packed runtime dependency graph, then executes unit tests, protobuf checks, a clean TypeScript build, npm pack --dry-run, and CommonJS, ESM, and TypeScript NodeNext smoke tests against the packed tarball in a temporary consumer. The packed tarball includes the TypeScript source and locked protobuf provenance in addition to compiled JavaScript and declarations.

TypeScript Example

Basic

import { SliverClient, ParseConfigFile } from 'sliver-script'

(async function() {
    
    const config = await ParseConfigFile('./localhost.cfg')
    const client = new SliverClient(config)

    await client.connect()

    const version = await client.getVersion()
    console.log(version)

    const sessions = await client.sessions()
    console.log(`Sessions: ${sessions.length}`)

    await client.disconnect()

})()

Monitor Events in Real-time

import { SliverClient, ParseConfigFile } from 'sliver-script'

(async function() {

    const config = await ParseConfigFile('./localhost.cfg')

    const client = new SliverClient(config)
    await client.connect()
    client.event$.subscribe((event) => {
        console.log(event)
    })

})()

Automatically Interact with New Sessions

import { SliverClient, ParseConfigFile } from 'sliver-script'


(async function() {

    const config = await ParseConfigFile('./localhost.cfg')
    const client = new SliverClient(config);
    await client.connect()

    console.log('Waiting for new sessions ...')
    client.session$.subscribe(async (event) => {
        console.log(`New session #${event.Session.ID}!`)
        const session = client.interactSession(event.Session.ID)
        const ls = await session.ls('.')
        console.log(`Path: ${ls.Path}`)
        ls.Files.forEach(file => {
            console.log(`Name: ${file.Name} (Size: ${file.Size})`)
        })
    })

})()

JavaScript Example

const sliver = require('sliver-script');

;(async function() {

    const config = await sliver.ParseConfigFile('./localhost.cfg')
    const client = new sliver.SliverClient(config)
    await client.connect()

    console.log('Waiting for new sessions ...')

    client.session$.subscribe(async (event) => {

        console.log(`New session #${event.Session.ID}!`)

        const session = client.interactSession(event.Session.ID)
        const ls = await session.ls('.')
        console.log(`Path: ${ls.Path}`)
        ls.Files.forEach(file => {
            console.log(`Name: ${file.Name} (Size: ${file.Size})`)
        })
        
    })

})()

About

TypeScript/JavaScript client libraries for Sliver

Resources

Stars

28 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages