diff --git a/dbus/proxy.go b/dbus/proxy.go
index 9f78648..59b887d 100644
--- a/dbus/proxy.go
+++ b/dbus/proxy.go
@@ -66,7 +66,7 @@ func (p *Proxy) String() string {
 	return "(unsealed dbus proxy)"
 }
 
-func (p *Proxy) Bwrap() []string {
+func (p *Proxy) BwrapStatic() []string {
 	return p.bwrap.Args()
 }
 
diff --git a/dbus/run.go b/dbus/run.go
index addf522..0a554bf 100644
--- a/dbus/run.go
+++ b/dbus/run.go
@@ -110,7 +110,7 @@ func (p *Proxy) Start(ready chan error, output io.Writer, sandbox bool) error {
 			bc.Bind(k, k)
 		}
 
-		h = helper.MustNewBwrap(bc, toolPath, p.seal, argF, nil)
+		h = helper.MustNewBwrap(bc, toolPath, p.seal, argF, nil, nil)
 		cmd = h.Unwrap()
 		p.bwrap = bc
 	}
diff --git a/fst/config.go b/fst/config.go
index ed0ac4c..72cb202 100644
--- a/fst/config.go
+++ b/fst/config.go
@@ -31,8 +31,6 @@ type ConfinementConfig struct {
 	Outer string `json:"home"`
 	// bwrap sandbox confinement configuration
 	Sandbox *SandboxConfig `json:"sandbox"`
-	// seccomp syscall filter configuration
-	Syscall *SyscallConfig `json:"syscall"`
 	// extra acl entries to append
 	ExtraPerms []*ExtraPermConfig `json:"extra_perms,omitempty"`
 
@@ -47,14 +45,6 @@ type ConfinementConfig struct {
 	Enablements system.Enablements `json:"enablements"`
 }
 
-type SyscallConfig struct {
-	DenyDevel bool `json:"deny_devel"`
-	Multiarch bool `json:"multiarch"`
-	Linux32   bool `json:"linux32"`
-	Can       bool `json:"can"`
-	Bluetooth bool `json:"bluetooth"`
-}
-
 type ExtraPermConfig struct {
 	Ensure  bool   `json:"ensure,omitempty"`
 	Path    string `json:"path"`
diff --git a/fst/sandbox.go b/fst/sandbox.go
index 8def908..0c3918a 100644
--- a/fst/sandbox.go
+++ b/fst/sandbox.go
@@ -22,6 +22,8 @@ type SandboxConfig struct {
 	Net bool `json:"net,omitempty"`
 	// share all devices
 	Dev bool `json:"dev,omitempty"`
+	// seccomp syscall filter policy
+	Syscall *bwrap.SyscallPolicy `json:"syscall"`
 	// do not run in new session
 	NoNewSession bool `json:"no_new_session,omitempty"`
 	// map target user uid to privileged user uid in the user namespace
@@ -50,6 +52,10 @@ func (s *SandboxConfig) Bwrap(os linux.System) (*bwrap.Config, error) {
 		return nil, errors.New("nil sandbox config")
 	}
 
+	if s.Syscall == nil {
+		fmsg.VPrintln("syscall filter not configured, PROCEED WITH CAUTION")
+	}
+
 	var uid int
 	if !s.MapRealUID {
 		uid = 65534
@@ -69,6 +75,7 @@ func (s *SandboxConfig) Bwrap(os linux.System) (*bwrap.Config, error) {
 		so this capacity should eliminate copies for most setups */
 		Filesystem: make([]bwrap.FSBuilder, 0, 256),
 
+		Syscall:       s.Syscall,
 		NewSession:    !s.NoNewSession,
 		DieWithParent: true,
 		AsInit:        true,
diff --git a/helper/bwrap.go b/helper/bwrap.go
index ad07731..851f244 100644
--- a/helper/bwrap.go
+++ b/helper/bwrap.go
@@ -9,25 +9,17 @@ import (
 	"sync"
 
 	"git.gensokyo.uk/security/fortify/helper/bwrap"
-	"git.gensokyo.uk/security/fortify/internal/proc"
 )
 
 // BubblewrapName is the file name or path to bubblewrap.
 var BubblewrapName = "bwrap"
 
-type BwrapExtraFile struct {
-	Name string
-	File *os.File
-}
-
 type bubblewrap struct {
 	// bwrap child file name
 	name string
 
 	// bwrap pipes
 	control *pipes
-	// extra files with fd passed as argument
-	extra []BwrapExtraFile
 	// returns an array of arguments passed directly
 	// to the child process spawned by bwrap
 	argF func(argsFD, statFD int) []string
@@ -54,14 +46,6 @@ func (b *bubblewrap) StartNotify(ready chan error) error {
 		return errors.New("exec: already started")
 	}
 
-	// pass extra fd to bwrap
-	for _, e := range b.extra {
-		if e.File == nil {
-			continue
-		}
-		b.Cmd.Args = append(b.Cmd.Args, e.Name, strconv.Itoa(int(proc.ExtraFile(b.Cmd, e.File))))
-	}
-
 	// prepare bwrap pipe and args
 	if argsFD, _, err := b.control.prepareCmd(b.Cmd); err != nil {
 		return err
@@ -130,9 +114,10 @@ func (b *bubblewrap) Unwrap() *exec.Cmd {
 func MustNewBwrap(
 	conf *bwrap.Config, name string,
 	wt io.WriterTo, argF func(argsFD, statFD int) []string,
-	extra []BwrapExtraFile,
+	extraFiles []*os.File,
+	syncFd *os.File,
 ) Helper {
-	b, err := NewBwrap(conf, name, wt, argF, extra)
+	b, err := NewBwrap(conf, name, wt, argF, extraFiles, syncFd)
 	if err != nil {
 		panic(err.Error())
 	} else {
@@ -146,23 +131,27 @@ func MustNewBwrap(
 func NewBwrap(
 	conf *bwrap.Config, name string,
 	wt io.WriterTo, argF func(argsFD, statFD int) []string,
-	extra []BwrapExtraFile,
+	extraFiles []*os.File,
+	syncFd *os.File,
 ) (Helper, error) {
 	b := new(bubblewrap)
 
-	if args, err := NewCheckedArgs(conf.Args()); err != nil {
-		return nil, err
-	} else {
-		b.control = &pipes{args: args}
-	}
-
-	b.extra = extra
 	b.argF = argF
 	b.name = name
 	if wt != nil {
 		b.controlPt = &pipes{args: wt}
 	}
+
 	b.Cmd = execCommand(BubblewrapName)
+	b.control = new(pipes)
+	args := conf.Args()
+	if fdArgs, err := conf.FDArgs(syncFd, &extraFiles); err != nil {
+		return nil, err
+	} else if b.control.args, err = NewCheckedArgs(append(args, fdArgs...)); err != nil {
+		return nil, err
+	} else {
+		b.Cmd.ExtraFiles = extraFiles
+	}
 
 	return b, nil
 }
diff --git a/helper/bwrap/arg.go b/helper/bwrap/arg.go
index efdab82..d419ba5 100644
--- a/helper/bwrap/arg.go
+++ b/helper/bwrap/arg.go
@@ -1,6 +1,13 @@
 package bwrap
 
-import "encoding/gob"
+import (
+	"encoding/gob"
+	"os"
+	"slices"
+	"strconv"
+
+	"git.gensokyo.uk/security/fortify/internal/proc"
+)
 
 type Builder interface {
 	Len() int
@@ -12,6 +19,11 @@ type FSBuilder interface {
 	Builder
 }
 
+type FDBuilder interface {
+	Len() int
+	Append(args *[]string, extraFiles *[]*os.File) error
+}
+
 func init() {
 	gob.Register(new(pairF))
 	gob.Register(new(stringF))
@@ -45,6 +57,33 @@ func (s stringF) Append(args *[]string) {
 	*args = append(*args, s[0], s[1])
 }
 
+type fileF struct {
+	name string
+	file *os.File
+}
+
+func (f *fileF) Len() int {
+	if f.file == nil {
+		return 0
+	}
+	return 2
+}
+
+func (f *fileF) Append(args *[]string, extraFiles *[]*os.File) error {
+	if f.file == nil {
+		return nil
+	}
+	extraFile(args, extraFiles, f.name, f.file)
+	return nil
+}
+
+func extraFile(args *[]string, extraFiles *[]*os.File, name string, f *os.File) {
+	if f == nil {
+		return
+	}
+	*args = append(*args, name, strconv.Itoa(int(proc.ExtraFileSlice(extraFiles, f))))
+}
+
 // Args returns a slice of bwrap args corresponding to c.
 func (c *Config) Args() (args []string) {
 	builders := []Builder{
@@ -75,3 +114,25 @@ func (c *Config) Args() (args []string) {
 
 	return
 }
+
+func (c *Config) FDArgs(syncFd *os.File, extraFiles *[]*os.File) (args []string, err error) {
+	builders := []FDBuilder{
+		&seccompBuilder{c},
+		&fileF{positionalArgs[SyncFd], syncFd},
+	}
+
+	argc := 0
+	for _, b := range builders {
+		argc += b.Len()
+	}
+
+	args = make([]string, 0, argc)
+	*extraFiles = slices.Grow(*extraFiles, len(builders))
+
+	for _, b := range builders {
+		if err = b.Append(&args, extraFiles); err != nil {
+			break
+		}
+	}
+	return
+}
diff --git a/helper/bwrap/config.go b/helper/bwrap/config.go
index 8def27a..b9fa0c1 100644
--- a/helper/bwrap/config.go
+++ b/helper/bwrap/config.go
@@ -47,6 +47,10 @@ type Config struct {
 	// (--chmod OCTAL PATH)
 	Chmod ChmodConfig `json:"chmod,omitempty"`
 
+	// load and use seccomp rules from FD (not repeatable)
+	// (--seccomp FD)
+	Syscall *SyscallPolicy
+
 	// create a new terminal session
 	// (--new-session)
 	NewSession bool `json:"new_session"`
@@ -70,7 +74,6 @@ type Config struct {
 	    --file FD DEST               Copy from FD to destination DEST
 	    --bind-data FD DEST          Copy from FD to file which is bind-mounted on DEST
 	    --ro-bind-data FD DEST       Copy from FD to file which is readonly bind-mounted on DEST
-	    --seccomp FD                 Load and use seccomp rules from FD (not repeatable)
 	    --add-seccomp-fd FD          Load and use seccomp rules from FD (repeatable)
 	    --block-fd FD                Block on FD until some data to read is available
 	    --userns-block-fd FD         Block on FD until the user namespace is ready
diff --git a/internal/proc/priv/shim/export.c b/helper/bwrap/seccomp-export.c
similarity index 99%
rename from internal/proc/priv/shim/export.c
rename to helper/bwrap/seccomp-export.c
index 404dd13..40e3bea 100644
--- a/internal/proc/priv/shim/export.c
+++ b/helper/bwrap/seccomp-export.c
@@ -2,7 +2,7 @@
 #define _GNU_SOURCE // CLONE_NEWUSER
 #endif
 
-#include "export.h"
+#include "seccomp-export.h"
 #include <stdlib.h>
 #include <stdio.h>
 #include <assert.h>
diff --git a/internal/proc/priv/shim/export.h b/helper/bwrap/seccomp-export.h
similarity index 100%
rename from internal/proc/priv/shim/export.h
rename to helper/bwrap/seccomp-export.h
diff --git a/helper/bwrap/seccomp-resolve.go b/helper/bwrap/seccomp-resolve.go
new file mode 100644
index 0000000..995a371
--- /dev/null
+++ b/helper/bwrap/seccomp-resolve.go
@@ -0,0 +1,95 @@
+package bwrap
+
+import (
+	"fmt"
+	"io"
+	"os"
+
+	"git.gensokyo.uk/security/fortify/internal/fmsg"
+)
+
+type SyscallPolicy struct {
+	DenyDevel bool `json:"deny_devel"`
+	Multiarch bool `json:"multiarch"`
+	Linux32   bool `json:"linux32"`
+	Can       bool `json:"can"`
+	Bluetooth bool `json:"bluetooth"`
+}
+
+type seccompBuilder struct {
+	config *Config
+}
+
+func (s *seccompBuilder) Len() int {
+	if s == nil {
+		return 0
+	}
+	return 2
+}
+
+func (s *seccompBuilder) Append(args *[]string, extraFiles *[]*os.File) error {
+	if s == nil {
+		return nil
+	}
+	if f, err := s.config.resolveSeccomp(); err != nil {
+		return err
+	} else {
+		extraFile(args, extraFiles, positionalArgs[Seccomp], f)
+		return nil
+	}
+}
+
+func (c *Config) resolveSeccomp() (*os.File, error) {
+	if c.Syscall == nil {
+		return nil, nil
+	}
+
+	// resolve seccomp filter opts
+	var (
+		opts    syscallOpts
+		optd    []string
+		optCond = [...]struct {
+			v bool
+			o syscallOpts
+			d string
+		}{
+			{!c.UserNS, flagDenyNS, "denyns"},
+			{c.NewSession, flagDenyTTY, "denytty"},
+			{c.Syscall.DenyDevel, flagDenyDevel, "denydevel"},
+			{c.Syscall.Multiarch, flagMultiarch, "multiarch"},
+			{c.Syscall.Linux32, flagLinux32, "linux32"},
+			{c.Syscall.Can, flagCan, "can"},
+			{c.Syscall.Bluetooth, flagBluetooth, "bluetooth"},
+		}
+	)
+	if CPrintln != nil {
+		optd = make([]string, 1, len(optCond)+1)
+		optd[0] = "common"
+	}
+	for _, opt := range optCond {
+		if opt.v {
+			opts |= opt.o
+			if fmsg.Verbose() {
+				optd = append(optd, opt.d)
+			}
+		}
+	}
+	if CPrintln != nil {
+		CPrintln(fmt.Sprintf("seccomp flags: %s", optd))
+	}
+
+	// export seccomp filter to tmpfile
+	if f, err := tmpfile(); err != nil {
+		return nil, err
+	} else {
+		return f, exportAndSeek(f, opts)
+	}
+}
+
+func exportAndSeek(f *os.File, opts syscallOpts) error {
+	if err := exportFilter(f.Fd(), opts); err != nil {
+		return err
+	}
+	_, err := f.Seek(0, io.SeekStart)
+	return err
+}
diff --git a/internal/proc/priv/shim/seccomp.go b/helper/bwrap/seccomp.go
similarity index 92%
rename from internal/proc/priv/shim/seccomp.go
rename to helper/bwrap/seccomp.go
index bf45874..abc2738 100644
--- a/internal/proc/priv/shim/seccomp.go
+++ b/helper/bwrap/seccomp.go
@@ -1,9 +1,9 @@
-package shim
+package bwrap
 
 /*
 #cgo linux pkg-config: --static libseccomp
 
-#include "export.h"
+#include "seccomp-export.h"
 */
 import "C"
 import (
@@ -11,10 +11,10 @@ import (
 	"fmt"
 	"os"
 	"runtime"
-
-	"git.gensokyo.uk/security/fortify/internal/fmsg"
 )
 
+var CPrintln func(v ...any)
+
 var resErr = [...]error{
 	0: nil,
 	1: errors.New("seccomp_init failed"),
@@ -77,5 +77,7 @@ func exportFilter(fd uintptr, opts syscallOpts) error {
 
 //export F_println
 func F_println(v *C.char) {
-	fmsg.VPrintln(C.GoString(v))
+	if CPrintln != nil {
+		CPrintln(C.GoString(v))
+	}
 }
diff --git a/helper/bwrap/sequential.go b/helper/bwrap/sequential.go
index 42a4b2b..1776c23 100644
--- a/helper/bwrap/sequential.go
+++ b/helper/bwrap/sequential.go
@@ -43,6 +43,9 @@ const (
 	Overlay
 	TmpOverlay
 	ROOverlay
+
+	SyncFd
+	Seccomp
 )
 
 var positionalArgs = [...]string{
@@ -70,6 +73,9 @@ var positionalArgs = [...]string{
 	Overlay:    "--overlay",
 	TmpOverlay: "--tmp-overlay",
 	ROOverlay:  "--ro-overlay",
+
+	SyncFd:  "--sync-fd",
+	Seccomp: "--seccomp",
 }
 
 type PermConfig[T FSBuilder] struct {
diff --git a/helper/bwrap_test.go b/helper/bwrap_test.go
index 9a565a4..0860d57 100644
--- a/helper/bwrap_test.go
+++ b/helper/bwrap_test.go
@@ -34,7 +34,7 @@ func TestBwrap(t *testing.T) {
 		h := helper.MustNewBwrap(
 			sc, "fortify",
 			argsWt, argF,
-			nil,
+			nil, nil,
 		)
 
 		if err := h.Start(); !errors.Is(err, os.ErrNotExist) {
@@ -47,7 +47,7 @@ func TestBwrap(t *testing.T) {
 		if got := helper.MustNewBwrap(
 			sc, "fortify",
 			argsWt, argF,
-			nil,
+			nil, nil,
 		); got == nil {
 			t.Errorf("MustNewBwrap(%#v, %#v, %#v) got nil",
 				sc, argsWt, "fortify")
@@ -67,7 +67,7 @@ func TestBwrap(t *testing.T) {
 		helper.MustNewBwrap(
 			&bwrap.Config{Hostname: "\x00"}, "fortify",
 			nil, argF,
-			nil,
+			nil, nil,
 		)
 	})
 
@@ -84,7 +84,7 @@ func TestBwrap(t *testing.T) {
 			helper.MustNewBwrap(
 				sc, "fortify",
 				nil, argF,
-				nil,
+				nil, nil,
 			).StartNotify(make(chan error))))
 	})
 
@@ -94,7 +94,7 @@ func TestBwrap(t *testing.T) {
 		h := helper.MustNewBwrap(
 			sc, "crash-test-dummy",
 			nil, argFChecked,
-			nil,
+			nil, nil,
 		)
 		cmd := h.Unwrap()
 
@@ -127,6 +127,6 @@ func TestBwrap(t *testing.T) {
 	})
 
 	t.Run("implementation compliance", func(t *testing.T) {
-		testHelper(t, func() helper.Helper { return helper.MustNewBwrap(sc, "crash-test-dummy", argsWt, argF, nil) })
+		testHelper(t, func() helper.Helper { return helper.MustNewBwrap(sc, "crash-test-dummy", argsWt, argF, nil, nil) })
 	})
 }
diff --git a/internal/app/app_pd_test.go b/internal/app/app_pd_test.go
index 968a11a..98ddf31 100644
--- a/internal/app/app_pd_test.go
+++ b/internal/app/app_pd_test.go
@@ -39,6 +39,7 @@ var testCasesPd = []sealTestCase{
 			Net:      true,
 			UserNS:   true,
 			Clearenv: true,
+			Syscall:  new(bwrap.SyscallPolicy),
 			Chdir:    "/home/chronos",
 			SetEnv: map[string]string{
 				"HOME":              "/home/chronos",
@@ -258,6 +259,7 @@ var testCasesPd = []sealTestCase{
 			UserNS:   true,
 			Chdir:    "/home/chronos",
 			Clearenv: true,
+			Syscall:  new(bwrap.SyscallPolicy),
 			SetEnv: map[string]string{
 				"DBUS_SESSION_BUS_ADDRESS": "unix:path=/run/user/65534/bus",
 				"DBUS_SYSTEM_BUS_ADDRESS":  "unix:path=/run/dbus/system_bus_socket",
diff --git a/internal/app/seal.go b/internal/app/seal.go
index bd0522a..228be5c 100644
--- a/internal/app/seal.go
+++ b/internal/app/seal.go
@@ -14,6 +14,7 @@ import (
 	"git.gensokyo.uk/security/fortify/acl"
 	"git.gensokyo.uk/security/fortify/dbus"
 	"git.gensokyo.uk/security/fortify/fst"
+	"git.gensokyo.uk/security/fortify/helper/bwrap"
 	"git.gensokyo.uk/security/fortify/internal/fmsg"
 	"git.gensokyo.uk/security/fortify/internal/linux"
 	"git.gensokyo.uk/security/fortify/internal/state"
@@ -52,8 +53,6 @@ type appSeal struct {
 	et system.Enablements
 	// initial config gob encoding buffer
 	ct io.WriterTo
-	// pass-through seccomp config from config
-	scmp *fst.SyscallConfig
 	// wayland socket direct access
 	directWayland bool
 	// extra UpdatePerm ops
@@ -196,6 +195,7 @@ func (a *app) Seal(config *fst.Config) error {
 		conf := &fst.SandboxConfig{
 			UserNS:       true,
 			Net:          true,
+			Syscall:      new(bwrap.SyscallPolicy),
 			NoNewSession: true,
 			AutoEtc:      true,
 		}
@@ -233,12 +233,6 @@ func (a *app) Seal(config *fst.Config) error {
 		conf.Filesystem = append(conf.Filesystem, &fst.FilesystemConfig{Src: "/dev/kvm", Device: true})
 
 		config.Confinement.Sandbox = conf
-
-		// ensure syscall filter
-		if config.Confinement.Syscall == nil {
-			config.Confinement.Syscall = new(fst.SyscallConfig)
-			config.Confinement.Syscall.Multiarch = true
-		}
 	}
 	seal.directWayland = config.Confinement.Sandbox.DirectWayland
 	if b, err := config.Confinement.Sandbox.Bwrap(a.os); err != nil {
@@ -259,9 +253,8 @@ func (a *app) Seal(config *fst.Config) error {
 	// initialise system interface with full uid
 	seal.sys.I = system.New(seal.sys.user.uid)
 
-	// pass through enablements and seccomp
+	// pass through enablements
 	seal.et = config.Confinement.Enablements
-	seal.scmp = config.Confinement.Syscall
 
 	// this method calls all share methods in sequence
 	if err := seal.setupShares([2]*dbus.Config{config.Confinement.SessionBus, config.Confinement.SystemBus}, a.os); err != nil {
diff --git a/internal/app/start.go b/internal/app/start.go
index 87bb6fd..d0a0116 100644
--- a/internal/app/start.go
+++ b/internal/app/start.go
@@ -76,11 +76,10 @@ func (a *app) Run(ctx context.Context, rs *RunState) error {
 
 		// send payload
 		if err = a.shim.Serve(shimSetupCtx, &shim.Payload{
-			Argv:    a.seal.command,
-			Exec:    shimExec,
-			Bwrap:   a.seal.sys.bwrap,
-			Home:    a.seal.sys.user.data,
-			Syscall: a.seal.scmp,
+			Argv:  a.seal.command,
+			Exec:  shimExec,
+			Bwrap: a.seal.sys.bwrap,
+			Home:  a.seal.sys.user.data,
 
 			Verbose: fmsg.Verbose(),
 		}); err != nil {
diff --git a/internal/proc/priv/shim/main.go b/internal/proc/priv/shim/main.go
index a92a3cf..85c5baf 100644
--- a/internal/proc/priv/shim/main.go
+++ b/internal/proc/priv/shim/main.go
@@ -2,8 +2,6 @@ package shim
 
 import (
 	"errors"
-	"flag"
-	"io"
 	"os"
 	"path"
 	"strconv"
@@ -20,7 +18,7 @@ import (
 // everything beyond this point runs as unconstrained target user
 // proceed with caution!
 
-func Main(args []string) {
+func Main() {
 	// sharing stdout with fortify
 	// USE WITH CAUTION
 	fmsg.SetPrefix("shim")
@@ -31,46 +29,6 @@ func Main(args []string) {
 		panic("unreachable")
 	}
 
-	set := flag.NewFlagSet("shim", flag.ExitOnError)
-
-	// debug: export seccomp filter
-	debugExportSeccomp := set.String("export-seccomp", "", "export the seccomp filter to file")
-	debugExportSeccompFlags := [...]struct {
-		o syscallOpts
-		v *bool
-	}{
-		{flagDenyNS, set.Bool("deny-ns", false, "deny namespace-related syscalls")},
-		{flagDenyTTY, set.Bool("deny-tty", false, "deny faking input ioctls")},
-		{flagDenyDevel, set.Bool("deny-devel", false, "deny development syscalls")},
-		{flagMultiarch, set.Bool("multiarch", false, "allow multiarch")},
-		{flagLinux32, set.Bool("linux32", false, "allow PER_LINUX32")},
-		{flagCan, set.Bool("can", false, "allow AF_CAN")},
-		{flagBluetooth, set.Bool("bluetooth", false, "AF_BLUETOOTH")},
-	}
-
-	// Ignore errors; set is set for ExitOnError.
-	_ = set.Parse(args[1:])
-
-	// debug: export seccomp filter
-	if *debugExportSeccomp != "" {
-		var opts syscallOpts
-		for _, opt := range debugExportSeccompFlags {
-			if *opt.v {
-				opts |= opt.o
-			}
-		}
-
-		if f, err := os.Create(*debugExportSeccomp); err != nil {
-			fmsg.Fatalf("cannot create %q: %v", *debugExportSeccomp, err)
-		} else {
-			mustExportFilter(f, opts)
-			if err = f.Close(); err != nil {
-				fmsg.Fatalf("cannot close %q: %v", *debugExportSeccomp, err)
-			}
-		}
-		fmsg.Exit(0)
-	}
-
 	// receive setup payload
 	var (
 		payload    Payload
@@ -169,23 +127,19 @@ func Main(args []string) {
 	conf.Symlink("fortify", innerInit)
 
 	helper.BubblewrapName = payload.Exec[0] // resolved bwrap path by parent
+	if fmsg.Verbose() {
+		bwrap.CPrintln = fmsg.Println
+	}
 	if b, err := helper.NewBwrap(
 		conf, innerInit,
 		nil, func(int, int) []string { return make([]string, 0) },
-		[]helper.BwrapExtraFile{
-			// keep this fd open while sandbox is running
-			// (--sync-fd FD)
-			{"--sync-fd", syncFd},
-			// load and use seccomp rules from FD (not repeatable)
-			// (--seccomp FD)
-			{"--seccomp", mustResolveSeccomp(payload.Bwrap, payload.Syscall)},
-		},
+		extraFiles,
+		syncFd,
 	); err != nil {
 		fmsg.Fatalf("malformed sandbox config: %v", err)
 	} else {
 		cmd := b.Unwrap()
 		cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
-		cmd.ExtraFiles = extraFiles
 
 		// run and pass through exit code
 		if err = b.Start(); err != nil {
@@ -200,65 +154,3 @@ func Main(args []string) {
 		}
 	}
 }
-
-func mustResolveSeccomp(bwrap *bwrap.Config, syscall *fst.SyscallConfig) (seccompFd *os.File) {
-	if syscall == nil {
-		fmsg.VPrintln("syscall filter not configured, PROCEED WITH CAUTION")
-		return
-	}
-
-	// resolve seccomp filter opts
-	var (
-		opts    syscallOpts
-		optd    []string
-		optCond = [...]struct {
-			v bool
-			o syscallOpts
-			d string
-		}{
-			{!bwrap.UserNS, flagDenyNS, "denyns"},
-			{bwrap.NewSession, flagDenyTTY, "denytty"},
-			{syscall.DenyDevel, flagDenyDevel, "denydevel"},
-			{syscall.Multiarch, flagMultiarch, "multiarch"},
-			{syscall.Linux32, flagLinux32, "linux32"},
-			{syscall.Can, flagCan, "can"},
-			{syscall.Bluetooth, flagBluetooth, "bluetooth"},
-		}
-	)
-	if fmsg.Verbose() {
-		optd = make([]string, 1, len(optCond)+1)
-		optd[0] = "fortify"
-	}
-	for _, opt := range optCond {
-		if opt.v {
-			opts |= opt.o
-			if fmsg.Verbose() {
-				optd = append(optd, opt.d)
-			}
-		}
-	}
-	if fmsg.Verbose() {
-		fmsg.VPrintf("seccomp flags: %s", optd)
-	}
-
-	// export seccomp filter to tmpfile
-	if f, err := tmpfile(); err != nil {
-		fmsg.Fatalf("cannot create tmpfile: %v", err)
-		panic("unreachable")
-	} else {
-		mustExportFilter(f, opts)
-		seccompFd = f
-		return
-	}
-}
-
-func mustExportFilter(f *os.File, opts syscallOpts) {
-	if err := exportFilter(f.Fd(), opts); err != nil {
-		fmsg.Fatalf("cannot export seccomp filter: %v", err)
-		panic("unreachable")
-	}
-	if _, err := f.Seek(0, io.SeekStart); err != nil {
-		fmsg.Fatalf("cannot lseek seccomp file: %v", err)
-		panic("unreachable")
-	}
-}
diff --git a/internal/proc/priv/shim/payload.go b/internal/proc/priv/shim/payload.go
index 2d6854f..e659e3f 100644
--- a/internal/proc/priv/shim/payload.go
+++ b/internal/proc/priv/shim/payload.go
@@ -1,7 +1,6 @@
 package shim
 
 import (
-	"git.gensokyo.uk/security/fortify/fst"
 	"git.gensokyo.uk/security/fortify/helper/bwrap"
 )
 
@@ -18,8 +17,6 @@ type Payload struct {
 	Home string
 	// sync fd
 	Sync *uintptr
-	// seccomp opts pass through
-	Syscall *fst.SyscallConfig
 
 	// verbosity pass through
 	Verbose bool
diff --git a/internal/system/dbus.go b/internal/system/dbus.go
index 3bed540..b74d5d3 100644
--- a/internal/system/dbus.go
+++ b/internal/system/dbus.go
@@ -99,7 +99,7 @@ func (d *DBus) apply(_ *I) error {
 	}
 	fmsg.VPrintln("starting message bus proxy:", d.proxy)
 	if fmsg.Verbose() { // save the extra bwrap arg build when verbose logging is off
-		fmsg.VPrintln("message bus proxy bwrap args:", d.proxy.Bwrap())
+		fmsg.VPrintln("message bus proxy bwrap args:", d.proxy.BwrapStatic())
 	}
 
 	// background wait for proxy instance and notify completion
diff --git a/ldd/exec.go b/ldd/exec.go
index eec31e4..23c4e89 100644
--- a/ldd/exec.go
+++ b/ldd/exec.go
@@ -23,7 +23,8 @@ func Exec(p string) ([]*Entry, error) {
 			NewSession:    true,
 			DieWithParent: true,
 		}).Bind("/", "/").DevTmpfs("/dev"), "ldd",
-		nil, func(_, _ int) []string { return []string{p} }, nil,
+		nil, func(_, _ int) []string { return []string{p} },
+		nil, nil,
 	); err != nil {
 		return nil, err
 	} else {
diff --git a/main.go b/main.go
index 8909e5b..e6e856b 100644
--- a/main.go
+++ b/main.go
@@ -291,7 +291,7 @@ func main() {
 
 	// internal commands
 	case "shim":
-		shim.Main(args)
+		shim.Main()
 		fmsg.Exit(0)
 	case "init":
 		init0.Main()